nextjs-layered-architecture
Skill0 starsChanged 16 days agoMITView on GitHub
Use when creating, moving, or naming files in a full-stack Next.js App Router app organized by technical layer (components, actions, services, queries, db). Best for small to mid-size apps. Covers layout, naming, import direction, server actions, TanStack Query, route handler exceptions, tests, and when to move to nextjs-domain-architecture.
- Reads credentials
In this repository7 other files it gives its agents.
The file
Show its rules and text
We split this skill into the rules it gives an agent
24 rules. About 0 are common, 10 are distinctive, and 14 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈10
Distinctive · estimate
This author's own choices. Worth a look.
14
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 17
Read src/ before creating files.
- Distinctive: line 43
Read references/full-tree.md when you need the expanded tree.
- Distinctive: line 45
Add a folder on first use.
- Very specific: line 46
Put a component in app/<route>/_components/ until a second route uses it, then move it to components/.
- Very specific: line 47
Every non-route folder inside app/ starts with _.
- Distinctive: line 75
Read references/data-fetching.md when writing a read, a mutation, or a prefetch.
- Very specific: line 85
Add app/api/<name>/route.ts only for: an auth library endpoint (Better Auth), tRPC, webhooks, streaming or SSE endpoints, or endpoints for …
- Distinctive: line 97
Put tests next to the file.
- Very specific: line 98
Put setup and helpers in test/.
- Distinctive: line 99
Test services and actions without rendering.
- Very specific: line 100
Put end-to-end tests in e2e/ at the repo root.
- Distinctive: line 104
Read references/growth-stages.md when deciding whether to restructure.
- Very specific: line 108
Use app/, components/, and lib/.
- Very specific: line 113
Use the default layout. Add subfolders inside a layer past about 10 files, for example services/billing/.
- Distinctive: line 122
Read references/anti-patterns.md when reviewing a layout or before moving files.
- Very specific: line 124
Do not put non-route folders in app/ without a leading _.
- Very specific: line 125
Do not put business logic in actions or components.
- Distinctive: line 126
Do not add a route handler where a server action works.
- Very specific: line 127
Do not call fetch to your own app from a server component.
- Distinctive: line 128
Do not write query keys inline.
- Very specific: line 129
Do not use a query for data a server component can render with 'use cache'.
- Very specific: line 130
Do not import services/ or db/ from client components.
- Very specific: line 131
Do not create common/, misc/, or helpers/ folders.
- Distinctive: line 132
Do not use PascalCase file names.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Next.js layered architecture
Full-stack Next.js App Router app, grouped by technical role. Routes stay thin in app/. Mutations use server actions. Use for small to mid-size projects. For large apps and teams, use nextjs-domain-architecture.
Target version
Written for Next.js 16 (App Router, React 19, TypeScript, Cache Components) and TanStack Query v5 on 2026-10-30. Pages Router is out of scope.
Follow the repo first
Read src/ before creating files. If the project already has conventions (folder names, casing, aliases), use them. Check tsconfig.json for aliases and next.config.ts for cacheComponents.
Default directory layout
src/
app/ # routes only: page, layout, loading, route.ts
_components/ # UI used by one route; nest per route as needed
api/ # route handlers, exceptions only (see below)
components/ # shared UI used by 2+ routes
ui/ # generic primitives (Button, Dialog)
providers/ # client providers (query, theme)
hooks/ # shared client hooks
queries/ # TanStack query keys, queryOptions, mutation hooks
actions/ # "use server" mutations and client-callable reads
services/ # server-only business logic
db/ # client, schema, migrations
schemas/ # zod schemas shared by forms and actions
lib/ # infrastructure and pure helpers
auth/ query/ # auth setup, query client
config/ # env parsing and constants
types/
styles/
test/Read references/full-tree.md when you need the expanded tree.
- Add a folder on first use. Do not create empty ones.
- Put a component in
app/<route>/_components/until a second route uses it, then move it tocomponents/. - Every non-route folder inside
app/starts with_.
Naming conventions
- Files and folders: kebab-case. Next special files keep their fixed names.
- Components:
UserCardinuser-card.tsx. Named exports, except where Next requires a default export (pages, layouts). - Actions:
create-user.action.ts, exportingcreateUserAction. - Queries:
user.queries.ts, exportinguserKeys,userListOptions,useCreateUser. - Services:
user.service.ts. Schemas:user.schema.ts. Types:user.types.ts. - Hooks:
use-thing.ts. - Tests:
user.service.test.tsnext to the file. - Imports:
@/maps tosrc/. Never use../../...
Dependency direction
app -> components -> hooks, queries -> actions -> services -> db -> libappmay import any layer below.componentsimporthooks,queries,lib,types. Neverapp,services, ordb.queriescallactionsonly. No server code.actionsvalidate withschemas, authorize, callservices, then revalidate. No business logic.servicesanddbimportserver-only. Server components may callservicesdirectly for reads.libandtypesimport nothing from the app.
Data and mutations
Read references/data-fetching.md when writing a read, a mutation, or a prefetch.
- Mutations: server actions. Use
useActionStatefor plain forms. UseuseMutationwhen the client cache must update. - Server cache:
'use cache'withcacheTaginservices/. Actions callupdateTagorrevalidateTag. - TanStack Query is for pagination, infinite scroll, lazy loading, polling, and client-side mutations. Do not use it for static, SEO-critical, or read-once data.
- Prefetch in the server page and wrap the client part in
HydrationBoundary. Await above-the-fold data. Stream the rest by not awaiting. - Query functions call server actions, not
fetch.
Route handlers: exceptions only
Add app/api/<name>/route.ts only for: an auth library endpoint (Better Auth), tRPC, webhooks, streaming or SSE endpoints, or endpoints for mobile and other platforms. Keep handlers thin and call services/. Everything else is a server action.
Where things live
- Config:
config/env.tsparsesprocess.envwith zod. Split server andNEXT_PUBLIC_vars. Readprocess.envnowhere else. List every var in.env.example. - Query client:
lib/query/get-query-client.ts. Provider incomponents/providers/. - Auth:
lib/auth/. Proxy (formerly middleware):src/proxy.ts. - Shared types:
types/. Keep a type next to its only user until a second file needs it. - Client state: local first. Keep server data in the query cache or server cache, not in a store.
Tests
- Put tests next to the file.
- Put setup and helpers in
test/. - Test services and actions without rendering. Test components with a query client wrapper.
- Put end-to-end tests in
e2e/at the repo root.
Structure at three sizes
Read references/growth-stages.md when deciding whether to restructure.
Prototype
Use app/, components/, and lib/. Add actions/, services/, db/ on first use.
Signal to move up: a database, or a second mutation.
Mid-size
Use the default layout. Add subfolders inside a layer past about 10 files, for example services/billing/.
Signal to move up: a layer passes about 30 files, one feature change touches 4+ top-level folders, or people collide in the same folders.
Large
Switch to nextjs-domain-architecture. Move one feature at a time.
Anti-patterns
Read references/anti-patterns.md when reviewing a layout or before moving files.
- Do not put non-route folders in
app/without a leading_. - Do not put business logic in actions or components. Use
services/. - Do not add a route handler where a server action works.
- Do not call
fetchto your own app from a server component. - Do not write query keys inline. Use the key factory.
- Do not use a query for data a server component can render with
'use cache'. - Do not import
services/ordb/from client components. - Do not create
common/,misc/, orhelpers/folders. - Do not use PascalCase file names.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

