agentleFS
htmujahidhtmujahid/project-structure-skills/skills/nextjs-layered-architecture/SKILL.md

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

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
  1. Very specific:

    Read src/ before creating files.

    line 17
  2. Distinctive:

    Read references/full-tree.md when you need the expanded tree.

    line 43
  3. Distinctive:

    Add a folder on first use.

    line 45
  4. Very specific:

    Put a component in app/<route>/_components/ until a second route uses it, then move it to components/.

    line 46
  5. Very specific:

    Every non-route folder inside app/ starts with _.

    line 47
  6. Distinctive:

    Read references/data-fetching.md when writing a read, a mutation, or a prefetch.

    line 75
  7. Very specific:

    Add app/api/<name>/route.ts only for: an auth library endpoint (Better Auth), tRPC, webhooks, streaming or SSE endpoints, or endpoints for …

    line 85
  8. Distinctive:

    Put tests next to the file.

    line 97
  9. Very specific:

    Put setup and helpers in test/.

    line 98
  10. Distinctive:

    Test services and actions without rendering.

    line 99
  11. Very specific:

    Put end-to-end tests in e2e/ at the repo root.

    line 100
  12. Distinctive:

    Read references/growth-stages.md when deciding whether to restructure.

    line 104
  13. Very specific:

    Use app/, components/, and lib/.

    line 108
  14. Very specific:

    Use the default layout. Add subfolders inside a layer past about 10 files, for example services/billing/.

    line 113
  15. Distinctive:

    Read references/anti-patterns.md when reviewing a layout or before moving files.

    line 122
  16. Very specific:

    Do not put non-route folders in app/ without a leading _.

    line 124
  17. Very specific:

    Do not put business logic in actions or components.

    line 125
  18. Distinctive:

    Do not add a route handler where a server action works.

    line 126
  19. Very specific:

    Do not call fetch to your own app from a server component.

    line 127
  20. Distinctive:

    Do not write query keys inline.

    line 128
  21. Very specific:

    Do not use a query for data a server component can render with 'use cache'.

    line 129
  22. Very specific:

    Do not import services/ or db/ from client components.

    line 130
  23. Very specific:

    Do not create common/, misc/, or helpers/ folders.

    line 131
  24. Distinctive:

    Do not use PascalCase file names.

    line 132

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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 to components/.
  • Every non-route folder inside app/ starts with _.

Naming conventions

  • Files and folders: kebab-case. Next special files keep their fixed names.
  • Components: UserCard in user-card.tsx. Named exports, except where Next requires a default export (pages, layouts).
  • Actions: create-user.action.ts, exporting createUserAction.
  • Queries: user.queries.ts, exporting userKeys, userListOptions, useCreateUser.
  • Services: user.service.ts. Schemas: user.schema.ts. Types: user.types.ts.
  • Hooks: use-thing.ts.
  • Tests: user.service.test.ts next to the file.
  • Imports: @/ maps to src/. Never use ../../...

Dependency direction

app -> components -> hooks, queries -> actions -> services -> db -> lib
  • app may import any layer below.
  • components import hooks, queries, lib, types. Never app, services, or db.
  • queries call actions only. No server code.
  • actions validate with schemas, authorize, call services, then revalidate. No business logic.
  • services and db import server-only. Server components may call services directly for reads.
  • lib and types import 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 useActionState for plain forms. Use useMutation when the client cache must update.
  • Server cache: 'use cache' with cacheTag in services/. Actions call updateTag or revalidateTag.
  • 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.ts parses process.env with zod. Split server and NEXT_PUBLIC_ vars. Read process.env nowhere else. List every var in .env.example.
  • Query client: lib/query/get-query-client.ts. Provider in components/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 fetch to 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/ or db/ from client components.
  • Do not create common/, misc/, or helpers/ folders.
  • Do not use PascalCase file names.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.