Next.js Routing Best Practices
A condensed summary of the 25 most important best practices drawn from every page in this section.
Search across all documentation pages
A condensed summary of the 25 most important best practices drawn from every page in this section.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
const { id } = await params - destructuring without await yields the Promise object and your lookups silently return undefined.page.tsx and a route.tsx - the Route Handler will shadow the page, so keep API routes under app/api/ to avoid silent conflicts.layout.tsx persists across navigation and its state survives child route changes; when you specifically need to remount (e.g., reset animations or state on each nav), use template.tsx instead.const postId = Number(params.id) - so coerce to the shape you actually need instead of trusting the type annotation alone.[...path] does not match the parent route, so /docs 404s; switch to [[...path]] or add a separate page.tsx alongside it when the base segment should resolve./blog/about/page.tsx next to [slug]/page.tsx without conflict.next build, so any unavailable data source fails the build; pair it with dynamicParams = true when new paths should still render on first request.error.tsx needs the "use client" directive - and it only catches errors below itself, never in the sibling layout.tsx at the same segment.global-error.tsx replaces the entire root layout when it triggers, so it must render its own <html><body>; also note it only activates in production (the dev overlay runs in development).try/catch swallows them - call them outside try/catch, or use unstable_rethrow in the catch block to let them propagate.not-found.tsx auto-catches any URL that does not match a route, while nested not-found.tsx files only fire when you explicitly call notFound() from within that subtree.searchParams; if a layout needs URL state, lift the logic into a page or a Client Component that uses useSearchParams() inside a Suspense boundary.useRouter, usePathname, and useSearchParams live in next/navigation; next/router is the Pages Router and silently fails or 404s when imported.useSearchParams() without a surrounding <Suspense> boundary opts the whole route into client-side rendering - always gate it: <Suspense fallback={null}><SearchFilters /></Suspense>.router.push() returns void, so wrap navigations in useTransition - startTransition(() => router.push("/dashboard")) - to get an isPending flag and disable buttons or show spinners during route changes.refresh() re-fetches server data for the active route only; other cached routes stay stale, so pair it with revalidateTag/revalidatePath when the mutation affects siblings.<Link> prefetches on viewport entry and scrolls to top by default - <Link href="/settings" prefetch={false} scroll={false}> - set prefetch={false} on rarely used links and scroll={false} for tab/filter UIs that should stay in place.config.matcher your middleware runs on every request including /_next/static and favicons - export const config = { matcher: ["/dashboard/:path*", "/api/:path*"] } - scope it explicitly and exclude redirect destinations to avoid infinite loops.bcrypt, fs, and most database drivers break at build or runtime - use Web APIs and edge-compatible libraries only.NextResponse.next() does not short-circuit; you must return it (or a redirect/rewrite) to actually stop the middleware chain, otherwise subsequent logic keeps executing.@slot folders must include a default.tsx fallback, otherwise hard navigations or mismatched subroutes 404; slots must also be direct children of the layout and cannot nest inside each other.(.), (..), (..)(..), and (...) count route-group segments the same as regular folders, so route groups may require an extra (..) hop; missing default.tsx in the hosting slot also breaks back-navigation dismiss.(group) folders cannot resolve to the same URL path (the build fails), and multiple root layouts force a full page reload between groups instead of soft navigation - keep the home route / in exactly one group.Reviewed by Chris St. John·Last updated Jul 19, 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥