Viet Tran a38d04c3d5
feat(search): overhaul relevance and curated design data
Overhaul BM25 relevance, reasoning and data-quality contracts; refresh UI styles and framework guidance; add resilient text, chip, badge and micro-interaction guidance; strengthen release, provenance and catalog refresh gates; update bilingual documentation.
2026-08-14 00:08:23 +07:00

22 KiB

1NoCategoryGuidelineDescriptionDoDon'tCode GoodCode BadSeverityDocs URLApplies ToStatusVerified At
21RoutingUse file-based routingCreate routes under the Nuxt 4 app pages directoryapp/pages with index.vueConfigure ordinary routes manuallyapp/pages/dashboard/index.vueCustom router setupMediumhttps://nuxt.com/docs/4.x/getting-started/routingnuxtjs 4.5active2026-08-13
32RoutingUse dynamic route parametersCreate dynamic routes with bracket syntax under app/pages[id].vue for dynamic paramsHardcode routes for dynamic contentapp/pages/posts/[id].vueapp/pages/posts/post1.vueMediumhttps://nuxt.com/docs/4.x/getting-started/routingnuxtjs 4.5active2026-08-13
43RoutingUse catch-all routesHandle multiple path segments with [...slug] under app/pages[...slug].vue for catch-allMultiply nested dynamic files unnecessarilyapp/pages/[...slug].vueapp/pages/[a]/[b]/[c].vueLowhttps://nuxt.com/docs/4.x/getting-started/routingnuxtjs 4.5active2026-08-13
54RoutingDefine page metadata with definePageMetaSet page-level configuration and middlewaredefinePageMeta for layout middleware titleManual route meta configurationdefinePageMeta({ layout: 'admin', middleware: 'auth' })router.beforeEach for page configHighhttps://nuxt.com/docs/4.x/api/utils/define-page-metanuxtjs 4.5active2026-08-13
65RoutingUse validate for route paramsValidate dynamic route parameters before renderingvalidate function in definePageMetaManual validation in setupdefinePageMeta({ validate: (route) => /^\d+$/.test(route.params.id) })if (!valid) navigateTo('/404')Mediumhttps://nuxt.com/docs/4.x/api/utils/define-page-metanuxtjs 4.5active2026-08-13
76RenderingUse SSR by defaultServer-side rendering is enabled by defaultKeep ssr: true (default)Disable SSR unnecessarilyssr: true (default)ssr: false for all pagesHighhttps://nuxt.com/docs/4.x/guide/concepts/renderingnuxtjs 4.5active2026-08-13
87RenderingUse .client suffix for client-only componentsMark components to render only on clientComponentName.client.vue suffixv-if with process.client checkComments.client.vue<div v-if="process.client"><Comments/></div>Mediumhttps://nuxt.com/docs/4.x/guide/directory-structure/componentsnuxtjs 4.5active2026-08-13
98RenderingUse .server suffix for server-only componentsMark components to render only on serverComponentName.server.vue suffixManual server checkHeavyMarkdown.server.vuev-if="process.server"Lowhttps://nuxt.com/docs/4.x/guide/directory-structure/componentsnuxtjs 4.5active2026-08-13
109DataFetchingUse useFetch for simple data fetchingWrapper around useAsyncData for URL fetchinguseFetch for API calls$fetch in onMountedconst { data } = await useFetch('/api/posts')onMounted(async () => { data.value = await $fetch('/api/posts') })Highhttps://nuxt.com/docs/4.x/api/composables/use-fetchnuxtjs 4.5active2026-08-13
1110DataFetchingUse useAsyncData for complex fetchingFine-grained control over async datauseAsyncData for CMS or custom fetchinguseFetch for non-URL data sourcesconst { data } = await useAsyncData('posts', () => cms.getPosts())const { data } = await useFetch(() => cms.getPosts())Mediumhttps://nuxt.com/docs/4.x/api/composables/use-async-datanuxtjs 4.5active2026-08-13
1211DataFetchingUse $fetch for non-reactive requests$fetch for event handlers and non-component code$fetch in event handlers or server routesuseFetch in click handlersasync function submit() { await $fetch('/api/submit', { method: 'POST' }) }async function submit() { await useFetch('/api/submit') }Highhttps://nuxt.com/docs/4.x/api/utils/dollarfetchnuxtjs 4.5active2026-08-13
1312DataFetchingUse lazy option for non-blocking fetchDefer data fetching for better initial loadlazy: true for below-fold contentBlocking fetch for non-critical datauseFetch('/api/comments', { lazy: true })await useFetch('/api/comments') for footerMediumhttps://nuxt.com/docs/4.x/api/composables/use-fetchnuxtjs 4.5active2026-08-13
1413DataFetchingUse server option intentionallyUse server:false only when data depends on browser-only stateserver:false for localStorage or browser APIsDisable SSR merely because data is user-specificuseFetch('/api/preferences', { server: false }) for browser-only inputserver:false for any authenticated requestMediumhttps://nuxt.com/docs/4.x/api/composables/use-fetchnuxtjs 4.5active2026-08-13
1514DataFetchingUse pick to reduce payload sizeSelect only needed fields from responsepick option for large responsesFetching entire objects when few fields neededuseFetch('/api/user', { pick: ['id', 'name'] })useFetch('/api/user') then destructureLowhttps://nuxt.com/docs/4.x/api/composables/use-fetchnuxtjs 4.5active2026-08-13
1615DataFetchingUse transform for data manipulationTransform data before storing in statetransform option for data shapingManual transformation after fetchuseFetch('/api/posts', { transform: (posts) => posts.map(p => p.title) })const titles = data.value.map(p => p.title)Lowhttps://nuxt.com/docs/4.x/api/composables/use-fetchnuxtjs 4.5active2026-08-13
1716DataFetchingHandle loading and error statesAlways handle pending and error statesCheck status pending error refsIgnoring loading states<div v-if="status === 'pending'">Loading...</div>No loading indicatorHighhttps://nuxt.com/docs/4.x/getting-started/data-fetchingnuxtjs 4.5active2026-08-13
1817LifecycleAvoid side effects in script setup rootMove side effects to lifecycle hooksSide effects in onMountedsetInterval in root script setuponMounted(() => { interval = setInterval(...) })<script setup>setInterval(...)</script>Highhttps://nuxt.com/docs/4.x/guide/concepts/nuxt-lifecyclenuxtjs 4.5active2026-08-13
1918LifecycleUse onMounted for DOM accessAccess DOM only after component is mountedonMounted for DOM manipulationDirect DOM access in setuponMounted(() => { document.getElementById('el') })<script setup>document.getElementById('el')</script>Highhttps://nuxt.com/docs/4.x/api/composables/on-mountednuxtjs 4.5active2026-08-13
2019LifecycleUse nextTick for post-render accessWait for DOM updates before accessing elementsawait nextTick() after state changesImmediate DOM access after state changecount.value++; await nextTick(); el.value.focus()count.value++; el.value.focus()Mediumhttps://nuxt.com/docs/4.x/api/utils/next-ticknuxtjs 4.5active2026-08-13
2120LifecycleUse onPrehydrate for pre-hydration logicRun code before Nuxt hydrates the pageonPrehydrate for client setuponMounted for hydration-critical codeonPrehydrate(() => { console.log(window) })onMounted for pre-hydration needsLowhttps://nuxt.com/docs/4.x/api/composables/on-prehydratenuxtjs 4.5active2026-08-13
2221ServerUse server/api for API routesCreate API endpoints in server/api directoryserver/api/users.ts for /api/usersManual Express setupserver/api/hello.ts -> /api/helloapp.get('/api/hello')Highhttps://nuxt.com/docs/4.x/guide/directory-structure/servernuxtjs 4.5active2026-08-13
2322ServerUse defineEventHandler for handlersDefine server route handlersdefineEventHandler for all handlersexport default functionexport default defineEventHandler((event) => { return { hello: 'world' } })export default function(req, res) {}Highhttps://nuxt.com/docs/4.x/guide/directory-structure/servernuxtjs 4.5active2026-08-13
2423ServerUse server/routes for non-api routesRoutes without /api prefixserver/routes for custom pathsserver/api for non-api routesserver/routes/sitemap.xml.tsserver/api/sitemap.xml.tsMediumhttps://nuxt.com/docs/4.x/guide/directory-structure/servernuxtjs 4.5active2026-08-13
2524ServerUse getQuery and readBody for inputAccess query params and request bodygetQuery(event) readBody(event)Direct event accessconst { id } = getQuery(event)event.node.req.queryMediumhttps://nuxt.com/docs/4.x/guide/directory-structure/servernuxtjs 4.5active2026-08-13
2625ServerValidate server inputAlways validate input in server handlersZod or similar for validationTrust client inputconst body = await readBody(event); schema.parse(body)const body = await readBody(event)Highhttps://nuxt.com/docs/4.x/guide/directory-structure/servernuxtjs 4.5active2026-08-13
2726StateUse useState for serializable shared stateShare SSR-safe values whose contents can be serializeduseState for JSON-serializable cross-component stateStore classes functions or symbolsconst count = useState('count', () => 0)useState('service' () => new Service())Highhttps://nuxt.com/docs/4.x/api/composables/use-statenuxtjs 4.5active2026-08-13
2827StateUse unique keys for useStatePrevent state conflicts with unique keysDescriptive unique keys for each stateGeneric or duplicate keysuseState('user-preferences', () => ({}))useState('data') in multiple placesMediumhttps://nuxt.com/docs/4.x/api/composables/use-statenuxtjs 4.5active2026-08-13
2928StateUse Pinia for complex statePinia for advanced state management@pinia/nuxt for complex appsCustom state managementuseMainStore() with PiniaCustom reactive store implementationMediumhttps://nuxt.com/docs/4.x/getting-started/state-managementnuxtjs 4.5active2026-08-13
3029StateUse callOnce for one-time async operationsEnsure async operations run only oncecallOnce for store initializationDirect await in componentawait callOnce(store.fetch)await store.fetch() on every renderMediumhttps://nuxt.com/docs/4.x/api/utils/call-oncenuxtjs 4.5active2026-08-13
3130SEOUse useSeoMeta for SEO tagsType-safe SEO meta tag managementuseSeoMeta for meta tagsuseHead for simple metauseSeoMeta({ title: 'Home', ogTitle: 'Home', description: '...' })useHead({ meta: [{ name: 'description', content: '...' }] })Highhttps://nuxt.com/docs/4.x/api/composables/use-seo-metanuxtjs 4.5active2026-08-13
3231SEOUse reactive values in useSeoMetaDynamic SEO tags with refs or gettersComputed getters for dynamic valuesStatic values for dynamic contentuseSeoMeta({ title: () => post.value.title })useSeoMeta({ title: post.value.title })Mediumhttps://nuxt.com/docs/4.x/api/composables/use-seo-metanuxtjs 4.5active2026-08-13
3332SEOUse useHead for non-meta head elementsScripts styles links in headuseHead for scripts and linksuseSeoMeta for scriptsuseHead({ script: [{ src: '/analytics.js' }] })useSeoMeta({ script: '...' })Mediumhttps://nuxt.com/docs/4.x/api/composables/use-headnuxtjs 4.5active2026-08-13
3433SEOInclude OpenGraph tagsAdd OG tags for social sharingogTitle ogDescription ogImageMissing social previewuseSeoMeta({ ogImage: '/og.png', twitterCard: 'summary_large_image' })No OG configurationMediumhttps://nuxt.com/docs/4.x/api/composables/use-seo-metanuxtjs 4.5active2026-08-13
3534MiddlewareUse defineNuxtRouteMiddlewareDefine route middleware under app/middlewaredefineNuxtRouteMiddleware wrapper in app/middlewarePut route middleware in server/middlewareexport default defineNuxtRouteMiddleware((to, from) => {})export default function(to, from) {}Highhttps://nuxt.com/docs/4.x/guide/directory-structure/app/middlewarenuxtjs 4.5active2026-08-13
3635MiddlewareUse navigateTo for redirectsRedirect in middleware with navigateToreturn navigateTo('/login')router.push in middlewareif (!auth) return navigateTo('/login')if (!auth) router.push('/login')Highhttps://nuxt.com/docs/4.x/api/utils/navigate-tonuxtjs 4.5active2026-08-13
3736MiddlewareReference middleware in definePageMetaApply app/middleware entries to specific pagesmiddleware array in definePageMetaUse global middleware for a page-specific concerndefinePageMeta({ middleware: ['auth'] })Global auth check for one pageMediumhttps://nuxt.com/docs/4.x/guide/directory-structure/app/middlewarenuxtjs 4.5active2026-08-13
3837MiddlewareUse .global suffix for global middlewareApply named route middleware globally with .global and keep it idempotent because initial SSR middleware can run again during hydrationapp/middleware/auth.global.ts with repeat-safe logicAssume it runs exactly onceapp/middleware/auth.global.tsIncrement state unconditionally on every middleware runMediumhttps://nuxt.com/docs/4.x/guide/directory-structure/app/middlewarenuxtjs 4.5active2026-08-13
3938ErrorHandlingUse createError for errorsCreate errors with proper status codescreateError with statusCodethrow new Errorthrow createError({ statusCode: 404, statusMessage: 'Not Found' })throw new Error('Not Found')Highhttps://nuxt.com/docs/4.x/api/utils/create-errornuxtjs 4.5active2026-08-13
4039ErrorHandlingUse NuxtErrorBoundary for local errorsHandle errors within component subtreeNuxtErrorBoundary for component errorsGlobal error page for local errors<NuxtErrorBoundary @error="log"><template #error="{ error }">error.vue for component errorsMediumhttps://nuxt.com/docs/4.x/getting-started/error-handlingnuxtjs 4.5active2026-08-13
4140ErrorHandlingUse clearError to recover from errorsClear error state and optionally redirectclearError({ redirect: '/' })Manual error state resetclearError({ redirect: '/home' })error.value = nullMediumhttps://nuxt.com/docs/4.x/api/utils/clear-errornuxtjs 4.5active2026-08-13
4241ErrorHandlingUse short statusMessageKeep statusMessage brief for securityShort generic messagesDetailed error info in statusMessagecreateError({ statusCode: 400, statusMessage: 'Bad Request' })createError({ statusMessage: 'Invalid user ID: 123' })Highhttps://nuxt.com/docs/4.x/getting-started/error-handlingnuxtjs 4.5active2026-08-13
4342LinkUse NuxtLink for internal navigationClient-side navigation with prefetching<NuxtLink to> for internal links<a href> for internal links<NuxtLink to="/about">About</NuxtLink><a href="/about">About</a>Highhttps://nuxt.com/docs/4.x/api/components/nuxt-linknuxtjs 4.5active2026-08-13
4443LinkConfigure prefetch behaviorControl when prefetching occursprefetchOn for interaction-basedDefault prefetch for low-priority<NuxtLink prefetch-on="interaction">Always default prefetchLowhttps://nuxt.com/docs/4.x/api/components/nuxt-linknuxtjs 4.5active2026-08-13
4544LinkUse useRouter for programmatic navigationNavigate programmaticallyuseRouter().push() for navigationDirect window.locationconst router = useRouter(); router.push('/dashboard')window.location.href = '/dashboard'Mediumhttps://nuxt.com/docs/4.x/api/composables/use-routernuxtjs 4.5active2026-08-13
4645LinkUse navigateTo in composablesNavigate outside componentsnavigateTo() in middleware or pluginsuseRouter in non-component codereturn navigateTo('/login')router.push in middlewareMediumhttps://nuxt.com/docs/4.x/api/utils/navigate-tonuxtjs 4.5active2026-08-13
4746AutoImportsUse Nuxt auto-imports intentionallyUse auto-imported Nuxt composables and Vue APIs or explicit imports consistentlyDirect use of useFetch and ref where auto-imports are enabledTreat valid explicit Vue imports as an errorconst count = ref(0)Mix unresolved globals after disabling importsMediumhttps://nuxt.com/docs/4.x/guide/concepts/auto-importsnuxtjs 4.5active2026-08-13
4847AutoImportsUse #imports for explicit Nuxt importsImport Nuxt-provided composables from #imports when an explicit import is usefulimport useRuntimeConfig from #importsImport Nuxt virtual composables from arbitrary package pathsimport { useRuntimeConfig } from '#imports'import { useRuntimeConfig } from 'nuxt'Lowhttps://nuxt.com/docs/4.x/guide/concepts/auto-importsnuxtjs 4.5active2026-08-13
4948AutoImportsConfigure third-party auto-importsAdd external package auto-importsimports.presets in nuxt.configManual imports everywhereimports: { presets: [{ from: 'vue-i18n', imports: ['useI18n'] }] }import { useI18n } everywhereLowhttps://nuxt.com/docs/4.x/guide/concepts/auto-importsnuxtjs 4.5active2026-08-13
5049PluginsUse defineNuxtPluginDefine plugins properlydefineNuxtPlugin wrapperexport default functionexport default defineNuxtPlugin((nuxtApp) => {})export default function(ctx) {}Highhttps://nuxt.com/docs/4.x/guide/directory-structure/pluginsnuxtjs 4.5active2026-08-13
5150PluginsUse provide for injectionProvide helpers across appreturn { provide: {} } for type safetynuxtApp.provide without typesreturn { provide: { hello: (name) => `Hello ${name}!` } }nuxtApp.provide('hello', fn)Mediumhttps://nuxt.com/docs/4.x/guide/directory-structure/pluginsnuxtjs 4.5active2026-08-13
5251PluginsUse .client or .server suffixControl plugin execution environmentplugin.client.ts for client-onlyif (process.client) checksanalytics.client.tsif (process.client) { // analytics }Mediumhttps://nuxt.com/docs/4.x/guide/directory-structure/pluginsnuxtjs 4.5active2026-08-13
5352EnvironmentUse runtimeConfig for env varsAccess environment variables safelyruntimeConfig in nuxt.configprocess.env directlyruntimeConfig: { apiSecret: '', public: { apiBase: '' } }process.env.API_SECRET in componentsHighhttps://nuxt.com/docs/4.x/guide/going-further/runtime-confignuxtjs 4.5active2026-08-13
5453EnvironmentDeclare keys before NUXT_ overridesDeclare every runtimeConfig key in nuxt.config before overriding it with a matching NUXT_ environment variableDeclared apiSecret and public.apiBase keys plus NUXT_API_SECRET or NUXT_PUBLIC_API_BASEExpect an undeclared environment variable to create configNUXT_PUBLIC_API_BASE=https://api.example.com after declaring public.apiBaseAPI_BASE=https://api.example.comHighhttps://nuxt.com/docs/4.x/guide/going-further/runtime-confignuxtjs 4.5active2026-08-13
5554EnvironmentAccess public config with useRuntimeConfigGet public config in componentsuseRuntimeConfig().publicDirect process.env accessconst config = useRuntimeConfig(); config.public.apiBaseprocess.env.NUXT_PUBLIC_API_BASEHighhttps://nuxt.com/docs/4.x/api/composables/use-runtime-confignuxtjs 4.5active2026-08-13
5655EnvironmentKeep secrets in private configServer-only secrets in runtimeConfig rootruntimeConfig.apiSecret (server only)Secrets in public configruntimeConfig: { dbPassword: '' }runtimeConfig: { public: { dbPassword: '' } }Highhttps://nuxt.com/docs/4.x/guide/going-further/runtime-confignuxtjs 4.5active2026-08-13
5756PerformanceUse Lazy prefix for code splittingLazy load components with Lazy prefix<LazyComponent> for below-foldEager load all components<LazyMountainsList v-if="show"/><MountainsList/> for hidden contentMediumhttps://nuxt.com/docs/4.x/guide/directory-structure/componentsnuxtjs 4.5active2026-08-13
5857PerformanceUse useLazyFetch for non-blocking dataAlias for useFetch with lazy: trueuseLazyFetch for secondary datauseFetch for all requestsconst { data } = useLazyFetch('/api/comments')await useFetch for comments sectionMediumhttps://nuxt.com/docs/4.x/api/composables/use-lazy-fetchnuxtjs 4.5active2026-08-13
5958PerformanceUse lazy hydration for interactivityDelay component hydration until neededLazyComponent with hydration strategyImmediate hydration for all<LazyModal hydrate-on-visible/><Modal/> in footerLowhttps://nuxt.com/docs/4.x/guide/going-further/experimental-featuresnuxtjs 4.5active2026-08-13
6059DataFetchingUse enabled for conditional async dataGate execution reactively with the enabled option instead of branching around the composableenabled: computed(() => Boolean(userId.value))Call useFetch conditionally after setupuseFetch('/api/user', { enabled: () => Boolean(userId.value) })if (userId.value) await useFetch('/api/user')Mediumhttps://nuxt.com/docs/4.x/api/composables/use-async-datanuxtjs 4.5active2026-08-13
6160DataFetchingKeep async-data handlers pureKeep useAsyncData handlers side-effect free and use stable explicit keysReturn a value from a pure handler with consistent optionsMutate shared state or vary options for one keyuseAsyncData('posts', () => $fetch('/api/posts'))useAsyncData('posts', async () => { store.count++; })Highhttps://nuxt.com/docs/4.x/api/composables/use-async-datanuxtjs 4.5active2026-08-13
6261DataFetchingRespect SSR request boundariesUse relative useFetch URLs to proxy safe request headers and cookies; forward only an explicit allowlist to external originsuseFetch for an internal relative URLAssume raw $fetch forwards request context or forward every incoming headerconst { data } = await useFetch('/api/profile')$fetch(externalUrl, { headers: useRequestHeaders() })Highhttps://nuxt.com/docs/4.x/api/utils/dollarfetchnuxtjs 4.5active2026-08-13
6362StateUse useCookie for SSR-safe cookiesRead and write cookies through the SSR-aware useCookie ref with explicit security optionsuseCookie with sameSite secure and httpOnly where server-onlyRead document.cookie during SSRuseCookie('session', { sameSite: 'lax', secure: true })document.cookieHighhttps://nuxt.com/docs/4.x/api/composables/use-cookienuxtjs 4.5active2026-08-13
6463RenderingUse routeRules for per-route renderingConfigure prerender SSR SPA redirects headers or cache behavior per route in nuxt.configrouteRules with explicit path patternsScatter rendering decisions through componentsrouteRules: { '/blog/**': { isr: 3600 } }process.client checks for route renderingHighhttps://nuxt.com/docs/4.x/guide/concepts/rendering#route-rulesnuxtjs 4.5active2026-08-13
6564ConfigurationSeparate app config from runtime configUse app.config for public reactive build-time app values and runtimeConfig for environment or secretsdefineAppConfig for theme and runtimeConfig for API secretsPut secrets in app.configdefineAppConfig({ theme: { primary: 'blue' } })defineAppConfig({ apiSecret: process.env.API_SECRET })Highhttps://nuxt.com/docs/4.x/guide/directory-structure/app/app-confignuxtjs 4.5active2026-08-13
6665StateRefresh externally changed cookiesCall refreshCookie when a cookie changes outside the useCookie refrefreshCookie after an external auth refreshAssume the ref observes every external changeawait refreshCookie('session')Keep stale session.value after external refreshMediumhttps://nuxt.com/docs/4.x/api/utils/refresh-cookienuxtjs 4.5active2026-08-13
6766StateReplace shallow-watched cookie valuesWhen cookie watch is shallow replace the top-level value to trigger serializationAssign a new object or arrayMutate a nested property in place with watch:'shallow'prefs.value = { ...prefs.value, theme: 'dark' }prefs.value.theme = 'dark'Mediumhttps://nuxt.com/docs/4.x/api/composables/use-cookienuxtjs 4.5active2026-08-13
6867MigrationMigrate Nuxt 3 before adding Nuxt 4 featuresNuxt 3 is end-of-life; use Nuxt 4 compatibility mode to surface directory app-config runtime-config and API changesEnable compatibilityVersion 4 and resolve migration warningsKeep an unmaintained Nuxt 3 app while adopting Nuxt 4-only guidancefuture: { compatibilityVersion: 4 }// Nuxt 3 retained without an upgrade planHighhttps://nuxt.com/blog/v4-5nuxtjs legacy 3.xdeprecated2026-08-13