Community content. Review instructions before giving them to an AI agent — treat modules like open-source code.
Next.js Project Conventions
App Router conventions: server-vs-client component defaults, safe env-variable exposure, and where data fetching and mutations belong.
Mby @markdownersPublished July 12, 2026 · Updated August 21, 2026 · ~2 min read
0 downloads · Used in: SaaS starter context
Project-level conventions for a Next.js (App Router) codebase, assuming Env & Secrets Hygiene@markdowners/env-and-secrets-hygiene's rules for anything env-related below, and Testing Strategy@markdowners/testing-strategy for how the test layout referenced here fits into the wider suite.
Server vs. client components
- Default every component to a Server Component; add a client-component directive only to the specific leaf components that actually need interactivity, browser APIs, or React state/effects — pushing that directive to the top of a large tree drags everything beneath it into the client bundle unnecessarily.
- Never import a server-only module (database client, secret-bearing SDK) into a file that's part of a client component's tree, even transitively — it either fails the build or, worse, gets bundled and shipped to the browser.
Data fetching
- Fetch data directly in Server Components (
async functioncomponents withawait) rather than client-side effect-plus-fetch for anything that can be known at render time — it removes a client-side loading waterfall and keeps secrets/queries server-side. - Use route-level loading and error boundaries for granular, streaming-friendly loading and error UI instead of manual boolean state for every data-fetching component.
Environment variables
- Only variables explicitly prefixed for client exposure (per the framework's convention) are safe in client-side code — every other variable is server-only by default and must stay that way; this specializes the general secrets-hygiene rule to Next.js's specific bundling behavior.
- Validate required environment variables at startup (a small schema check run once) rather than discovering a missing variable via a runtime crash deep in a request handler.
File and folder structure
- Colocate a route's own components, tests, and styles within its route segment folder; keep only genuinely shared, cross-route code in a top-level shared directory — this keeps "what does this route depend on" locally answerable.
- Use route groups to organize routes without affecting the URL structure, rather than deeply nested folders that don't reflect the actual URL.
Server actions and mutations
- Validate all input to a Server Action server-side (never trust that client-side form validation ran) — a Server Action is a public API endpoint with a different calling convention, not a trusted RPC.
- Keep Server Actions focused (one mutation, one action) rather than a single catch-all action branching on a "type" parameter — it keeps authorization checks per-action instead of a branch that's easy to under-guard.
Metadata and rendering
- Use the framework's typed metadata API per route rather than manually constructed head tags, so metadata stays server-rendered and type-checked.
- Default to static/server rendering; opt into dynamic rendering deliberately (and know why) rather than accidentally forcing every route dynamic through an unnoticed uncached data call.
Requires
- Env & Secrets Hygiene@markdowners/env-and-secrets-hygiene
You might also add
- Testing Strategysuggested
Badge
Link back to this module from your own README.
[](https://markdowners.com/m/markdowners/nextjs-project-conventions)Discussions about this module
No discussions about this module yet.
Start a discussion
Comments (0)
Sign in to comment. Sign in
No comments yet. Be the first to add one.