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

18 KiB

1NoCategoryGuidelineDescriptionDoDon'tCode GoodCode BadSeverityDocs URLApplies ToStatusVerified At
21RoutingUse App Router for new projectsApp Router is the recommended approach in Next.js 14+app/ directory with page.tsxpages/ for new projectsapp/dashboard/page.tsxpages/dashboard.tsxMediumhttps://nextjs.org/docs/appnextjs 16.2active2026-08-13
32RoutingUse file-based routingCreate routes by adding files in app directorypage.tsx for routes layout.tsx for layoutsManual route configurationapp/blog/[slug]/page.tsxCustom router setupMediumhttps://nextjs.org/docs/app/building-your-application/routingnextjs 16.2active2026-08-13
43RoutingColocate related filesKeep components styles tests with their routesComponent files alongside page.tsxSeparate components folderapp/dashboard/_components/components/dashboard/Lownextjs 16.2active2026-08-13
54RoutingUse route groups for organizationGroup routes without affecting URLParentheses for route groupsNested folders affecting URL(marketing)/about/page.tsxmarketing/about/page.tsxLowhttps://nextjs.org/docs/app/building-your-application/routing/route-groupsnextjs 16.2active2026-08-13
65RoutingHandle loading statesUse loading.tsx for route loading UIloading.tsx alongside page.tsxManual loading state managementapp/dashboard/loading.tsxuseState for loading in pageMediumhttps://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streamingnextjs 16.2active2026-08-13
76RoutingHandle errors with error.tsxCatch errors at route levelerror.tsx with reset functiontry/catch in every componentapp/dashboard/error.tsxtry/catch in page componentHighhttps://nextjs.org/docs/app/building-your-application/routing/error-handlingnextjs 16.2active2026-08-13
87RenderingUse Server Components by defaultServer Components reduce client JS bundleKeep components server by defaultAdd 'use client' unnecessarilyexport default function Page()('use client') for static contentHighhttps://nextjs.org/docs/app/building-your-application/rendering/server-componentsnextjs 16.2active2026-08-13
98RenderingMark Client Components explicitly'use client' for interactive componentsAdd 'use client' only when neededServer Component with hooks/events('use client') for onClick useStateNo directive with useStateHighhttps://nextjs.org/docs/app/building-your-application/rendering/client-componentsnextjs 16.2active2026-08-13
109RenderingPush Client Components downKeep Client Components as leaf nodesClient wrapper for interactive parts onlyMark page as Client Component<InteractiveButton/> in Server Page('use client') on page.tsxHighhttps://nextjs.org/docs/app/building-your-application/rendering/client-componentsnextjs 16.2active2026-08-13
1110RenderingUse streaming for better UXStream content with Suspense boundariesSuspense for slow data fetchesWait for all data before render<Suspense><SlowComponent/></Suspense>await allData then renderMediumhttps://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streamingnextjs 16.2active2026-08-13
1211RenderingChoose correct rendering strategySSG for static SSR for dynamic ISR for semi-staticgenerateStaticParams for known pathsSSR for static contentexport const revalidate = 3600fetch without cache configMediumnextjs 16.2active2026-08-13
1312DataFetchingFetch data in Server ComponentsFetch directly in async Server Componentsasync function Page() { const data = await fetch() }useEffect for initial dataconst data = await fetch(url)useEffect(() => fetch(url))Highhttps://nextjs.org/docs/app/building-your-application/data-fetchingnextjs 16.2active2026-08-13
1413DataFetchingConfigure caching explicitly (Next.js 16.2+)Next.js 16 uses Cache Components and explicit cache directives instead of assuming fetch is the cache model.Set cache semantics explicitly for static and dynamic dataAssume fetch defaults alone define the cache modelfetch(url, { cache: 'force-cache' })fetch(url) // Uncached in v15Highhttps://nextjs.org/docs/app/guides/upgrading/version-16nextjs 16.2active2026-08-13
1514DataFetchingDeduplicate fetch requestsReact and Next.js dedupe same requestsSame fetch call in multiple componentsManual request deduplicationMultiple components fetch same URLCustom cache layerLownextjs 16.2active2026-08-13
1615DataFetchingUse Server Actions for mutationsServer Actions for form submissionsaction={serverAction} in formsAPI route for every mutation<form action={createPost}><form onSubmit={callApiRoute}>Mediumhttps://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutationsnextjs 16.2active2026-08-13
1716DataFetchingRevalidate or update data appropriatelyUse updateTag for immediate read-your-own-writes and revalidateTag(..., "max") for SWR invalidation.Use updateTag after mutations that should be visible immediatelyRely on router.refresh() as the default mutation strategyrevalidatePath('/posts')router.refresh() everywhereMediumhttps://nextjs.org/docs/app/api-reference/functions/updateTagnextjs 16.2active2026-08-13
1817ImagesUse next/image for optimizationAutomatic image optimization and lazy loading<Image> component for all images<img> tags directly<Image src={} alt={} width={} height={}><img src={}/>Highhttps://nextjs.org/docs/app/building-your-application/optimizing/imagesnextjs 16.2active2026-08-13
1918ImagesProvide width and heightPrevent layout shift with dimensionswidth and height props or fillMissing dimensions<Image width={400} height={300}/><Image src={url}/>Highhttps://nextjs.org/docs/app/api-reference/components/imagenextjs 16.2active2026-08-13
2019ImagesUse fill for responsive imagesFill container with object-fitfill prop with relative parentFixed dimensions for responsive<Image fill className="object-cover"/><Image width={window.width}/>Mediumnextjs 16.2active2026-08-13
2120ImagesConfigure remote image domainsWhitelist external image sourcesremotePatterns in next.config.jsAllow all domainsremotePatterns: [{ hostname: 'cdn.example.com' }]domains: ['*']Highhttps://nextjs.org/docs/app/api-reference/components/image#remotepatternsnextjs 16.2active2026-08-13
2221ImagesUse priority for LCP imagesMark above-fold images as prioritypriority prop on hero imagesAll images with priority<Image priority src={hero}/><Image priority/> on every imageMediumnextjs 16.2active2026-08-13
2322FontsUse next/font for fontsSelf-hosted fonts with zero layout shiftnext/font/google or next/font/localExternal font linksimport { Inter } from 'next/font/google'<link href="fonts.googleapis.com"/>Mediumhttps://nextjs.org/docs/app/building-your-application/optimizing/fontsnextjs 16.2active2026-08-13
2423FontsApply font to layoutSet font in root layout for consistencyclassName on body in layout.tsxFont in individual pages<body className={inter.className}>Each page imports fontLownextjs 16.2active2026-08-13
2524FontsUse variable fontsVariable fonts reduce bundle sizeSingle variable font fileMultiple font weights as filesInter({ subsets: ['latin'] })Inter_400 Inter_500 Inter_700Lownextjs 16.2active2026-08-13
2625MetadataUse generateMetadata for dynamicGenerate metadata based on paramsexport async function generateMetadata()Hardcoded metadata everywheregenerateMetadata({ params })export const metadata = {}Mediumhttps://nextjs.org/docs/app/building-your-application/optimizing/metadatanextjs 16.2active2026-08-13
2726MetadataInclude OpenGraph imagesAdd OG images for social sharingopengraph-image.tsx or og propertyMissing social preview imagesopengraph: { images: ['/og.png'] }No OG configurationMediumnextjs 16.2active2026-08-13
2827MetadataUse metadata APIExport metadata object for static metadataexport const metadata = {}Manual head tagsexport const metadata = { title: 'Page' }<head><title>Page</title></head>Mediumnextjs 16.2active2026-08-13
2928APIUse Route Handlers for APIsapp/api routes for API endpointsapp/api/users/route.tspages/api for new projectsexport async function GET(request)export default function handlerMediumhttps://nextjs.org/docs/app/building-your-application/routing/route-handlersnextjs 16.2active2026-08-13
3029APIReturn proper Response objectsUse NextResponse for API responsesNextResponse.json() for JSONPlain objects or res.json()return NextResponse.json({ data })return { data }Mediumnextjs 16.2active2026-08-13
3130APIHandle HTTP methods explicitlyExport named functions for methodsExport GET POST PUT DELETESingle handler for all methodsexport async function POST()switch(req.method)Lownextjs 16.2active2026-08-13
3231APIValidate request bodyValidate input before processingZod or similar for validationTrust client inputconst body = schema.parse(await req.json())const body = await req.json()Highhttps://nextjs.org/docs/app/guides/data-securitynextjs 16.2active2026-08-13
3332MiddlewareUse proxy.ts for auth and request guardsNext.js 16 renamed middleware to proxy to reflect its network-boundary role.Use proxy.ts for redirects, rewrites, and lightweight request guardsKeep new auth logic in middleware.tsexport function proxy(request)if (!session) redirect in pageMediumhttps://nextjs.org/docs/app/guides/upgrading/version-16nextjs 16.2active2026-08-13
3433MiddlewareMatch specific proxy pathsConfigure the proxy matcherconfig.matcher for specific routesRun proxy on all routesmatcher: ['/dashboard/:path*']No matcher configMediumhttps://nextjs.org/docs/app/getting-started/proxynextjs 16.2active2026-08-13
3534MiddlewareKeep proxy runtime-safeProxy runs in nodejs runtime and fetch cache options do not apply there.Keep proxy logic lightweight and nodejs-compatibleUse Node-incompatible code or rely on fetch cache options in proxyEdge-compatible auth checkfs.readFile in middlewareHighhttps://nextjs.org/docs/app/getting-started/proxynextjs 16.2active2026-08-13
3635EnvironmentUse NEXT_PUBLIC prefixClient-accessible env vars need prefixNEXT_PUBLIC_ for client varsServer vars exposed to clientNEXT_PUBLIC_API_URLAPI_SECRET in client codeHighhttps://nextjs.org/docs/app/building-your-application/configuring/environment-variablesnextjs 16.2active2026-08-13
3736EnvironmentValidate env varsCheck required env vars existValidate on startupUndefined env at runtimeif (!process.env.DATABASE_URL) throwprocess.env.DATABASE_URL (might be undefined)Highhttps://nextjs.org/docs/app/guides/data-securitynextjs 16.2active2026-08-13
3837EnvironmentUse .env.local for secretsLocal env file for development secrets.env.local gitignoredSecrets in .env committed.env.local with secrets.env with DATABASE_PASSWORDHighhttps://nextjs.org/docs/app/guides/data-securitynextjs 16.2active2026-08-13
3938PerformanceAnalyze bundle sizeUse @next/bundle-analyzerBundle analyzer in devShip large bundles blindlyANALYZE=true npm run buildNo bundle analysisMediumhttps://nextjs.org/docs/app/building-your-application/optimizing/bundle-analyzernextjs 16.2active2026-08-13
4039PerformanceUse dynamic importsCode split with next/dynamicdynamic() for heavy componentsImport everything staticallyconst Chart = dynamic(() => import('./Chart'))import Chart from './Chart'Mediumhttps://nextjs.org/docs/app/building-your-application/optimizing/lazy-loadingnextjs 16.2active2026-08-13
4140PerformanceAvoid layout shiftsReserve space for dynamic contentSkeleton loaders aspect ratiosContent popping in<Skeleton className="h-48"/>No placeholder for async contentHighhttps://nextjs.org/docs/app/api-reference/components/imagenextjs 16.2active2026-08-13
4241PerformanceUse Partial PrerenderingCombine static and dynamic in one routeStatic shell with Suspense holesFull dynamic or static pagesStatic header + dynamic contentEntire page SSRLowhttps://nextjs.org/docs/app/building-your-application/rendering/partial-prerenderingnextjs 16.2active2026-08-13
4342LinkUse next/link for navigationClient-side navigation with prefetching<Link href=""> for internal links<a> for internal navigation<Link href="/about">About</Link><a href="/about">About</a>Highhttps://nextjs.org/docs/app/api-reference/components/linknextjs 16.2active2026-08-13
4443LinkPrefetch strategicallyControl prefetching behaviorprefetch={false} for low-priorityPrefetch all links<Link prefetch={false}>Default prefetch on every linkLownextjs 16.2active2026-08-13
4544LinkUse scroll option appropriatelyControl scroll behavior on navigationscroll={false} for tabs paginationAlways scroll to top<Link scroll={false}>Manual scroll managementLownextjs 16.2active2026-08-13
4645ConfigUse next.config.ts correctlyUse current Next.js 16 config names such as cacheComponents and skipProxyUrlNormalize.Proper config optionsDeprecated or wrong optionsimages: { remotePatterns: [] }images: { domains: [] }Mediumhttps://nextjs.org/docs/app/api-reference/next-config-jsnextjs 16.2active2026-08-13
4746ConfigEnable strict modeCatch potential issues earlyreactStrictMode: trueStrict mode disabledreactStrictMode: truereactStrictMode: falseMediumnextjs 16.2active2026-08-13
4847ConfigConfigure redirects and rewritesUse config for URL managementredirects() rewrites() in configManual redirect handlingredirects: async () => [...]res.redirect in pagesMediumhttps://nextjs.org/docs/app/api-reference/next-config-js/redirectsnextjs 16.2active2026-08-13
4948DeploymentUse Vercel for easiest deployVercel optimized for Next.jsDeploy to VercelSelf-host without knowledgevercel deployComplex Docker setup for simple appLowhttps://nextjs.org/docs/app/building-your-application/deployingnextjs 16.2active2026-08-13
5049DeploymentConfigure output for self-hostingSet output option for deployment targetoutput: 'standalone' for DockerDefault output for containersoutput: 'standalone'No output config for DockerMediumhttps://nextjs.org/docs/app/building-your-application/deploying#self-hostingnextjs 16.2active2026-08-13
5150SecuritySanitize user inputSanitize and validate any user-controlled data before rendering or mutating.Escape sanitize validate all inputDirect interpolation of user dataDOMPurify.sanitize(userInput)dangerouslySetInnerHTML={{ __html: userInput }}Highhttps://nextjs.org/docs/app/guides/data-securitynextjs 16.2active2026-08-13
5251SecurityUse CSP headersContent Security Policy for XSS protectionConfigure CSP in next.config.jsNo security headersheaders() with CSPNo CSP configurationHighhttps://nextjs.org/docs/app/building-your-application/configuring/content-security-policynextjs 16.2active2026-08-13
5352SecurityValidate Server Action inputServer Actions are public endpoints, so they need validation and authorization.Validate and authorize in Server ActionTrust Server Action inputAuth check + validation in actionDirect database call without checkHighhttps://nextjs.org/docs/app/guides/data-securitynextjs 16.2active2026-08-13
5453CachingUse Cache Components as the current cache modelCache Components is the current Next.js 16 cache model and the foundation for use cache, cacheLife, cacheTag, and updateTag.Enable cacheComponents for routes that should use the new cache modelTreat the old fetch-only mental model as the primary cache contractconst nextConfig = { cacheComponents: true }const nextConfig = { experimental: { ppr: true } }Highhttps://nextjs.org/blog/next-16nextjs 16.2active2026-08-13
5554CachingUse use cache for cacheable functions and componentsThe use cache directive marks a route, component, or function as cacheable under Cache Components.Place use cache at file, component, or function scope where the result is cacheableCache runtime-sensitive data without passing it in as arguments'use cache' export default async function Page() { }export default async function Page() { /* uncached by accident */ }Highhttps://nextjs.org/docs/app/api-reference/directives/use-cachenextjs 16.2active2026-08-13
5655CachingSet cache lifetime with cacheLifeUse cacheLife with use cache to make cache freshness explicit and readable.Choose a cacheLife profile that matches update frequencyLeave cache behavior implicit when the data has a known freshness windowcacheLife('days')/* implicit default */Mediumhttps://nextjs.org/docs/app/api-reference/functions/cacheLifenextjs 16.2active2026-08-13
5756CachingTag cache entries with cacheTagUse cacheTag inside cached scopes to support targeted invalidation.Assign stable tags to cacheable dataUse broad invalidation when a specific tag is enoughcacheTag('posts')/* no tag, broad invalidation later */Mediumhttps://nextjs.org/docs/app/api-reference/functions/cacheTagnextjs 16.2active2026-08-13
5857CachingUse updateTag for read-your-own-writesUse updateTag from Server Actions when the UI must reflect a mutation immediately.Call updateTag after a successful mutation in a Server ActionUse updateTag outside Server ActionsupdateTag('cart')revalidateTag('cart') // when immediate refresh is requiredHighhttps://nextjs.org/docs/app/api-reference/functions/updateTagnextjs 16.2active2026-08-13
5958CachingUse revalidateTag(..., "max") for SWR invalidationThe one-argument revalidateTag form is deprecated; profile="max" is the current stale-while-revalidate contract.Use revalidateTag(tag, "max") for background refresh semanticsRely on the deprecated single-argument revalidateTag(tag)revalidateTag('posts', 'max')revalidateTag('posts')Highhttps://nextjs.org/docs/app/api-reference/functions/revalidateTagnextjs 16.2active2026-08-13
6059MiddlewareUse proxy.ts for request interceptionNext.js 16 renamed middleware to proxy; the proxy runtime is nodejs and fetch cache options have no effect there.Use proxy.ts for redirects, rewrites, and lightweight guardsAssume proxy is edge runtime or use fetch cache semantics thereexport function proxy(request) { return NextResponse.next() }export function middleware(request) { return NextResponse.next() }Highhttps://nextjs.org/docs/app/getting-started/proxynextjs 16.2active2026-08-13
6160MiddlewareTreat middleware.ts and export function middleware as legacyThe middleware filename and named export are deprecated in Next.js 16; use proxy.ts and export function proxy instead.Rename middleware.ts to proxy.ts during migrationIntroduce new middleware.ts codeproxy.tsmiddleware.tsHighhttps://nextjs.org/docs/app/guides/upgrading/version-16nextjs legacydeprecated2026-08-13