Folder structure and code organization for React + Next.js (App Router) projects. Use this skill whenever the user asks where files should live (components, hooks, utils, helpers, lib, services, constants, types), how to break a component into smaller pieces, how to organize a feature folder, where to put business logic, when to use a barrel index, or how to lay out app/ in Next.js (route groups, private folders). Trigger on phrases like 'folder structure', 'project structure', 'where should I put', 'how to organize', 'where do constants go', 'utils vs helpers', 'app router structure'. Covers organization decisions only — NOT React hook rules or render patterns (use engineering-paved-path:react-best-practices) and NOT Next-specific runtime behavior (use engineering-paved-path:next-best-practices).
How this skill is triggered — by the user, by Claude, or both
Slash command
/engineering-paved-path:frontend-architectureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Where files should live in a React + Next.js (App Router) project. **Organization decisions only** — not hook rules (see `engineering-paved-path:react-best-practices`), not RSC / runtime behavior (see `engineering-paved-path:next-best-practices`).
Where files should live in a React + Next.js (App Router) project. Organization decisions only — not hook rules (see engineering-paved-path:react-best-practices), not RSC / runtime behavior (see engineering-paved-path:next-best-practices).
For concrete folder-tree examples, see examples.md. For sources, version history, and relationship to other skills, see README.md.
Each rule is tagged for use by consuming agents:
src/ for non-trivial appssrc/; Next.js looks for src/app if app/ is not at the rootapp/ at root and src/app/ togethersrc/
├── app/ # Next.js: routing only. Vite: not used
├── components/ # Shared, generic UI (Button, Card, Modal)
├── features/ # Domain-scoped modules (one folder per feature)
├── hooks/ # Shared, generic hooks (useDebounce, useMediaQuery)
├── lib/ # Wrappers around external libs (axios.ts, db.ts, auth.ts)
├── utils/ # Pure, generic, project-agnostic functions
├── types/ # Shared types (only if not feature-scoped)
└── constants/ # Cross-feature constants (routes, env keys, enums)
Each of these folders is optional — introduce it only when there are ≥2 things to put in it.
features/Add features/ once the app has ≥2 distinct domains (e.g. "billing", "settings", "team"). Before that, a flat components/ + hooks/ is fine. Don't pre-create features/ on day 1.
| Style | When | Trade-off |
|---|---|---|
By type (components/, hooks/, utils/) | Small apps (<30 files) | Easy start, breaks down past ~50 files |
| Feature-based | Default for product apps | Best balance of discoverability and scope |
| Layer-based / FSD | Large, multi-team apps with enforced boundaries | High ceremony; real wins only past ~500 files |
| Atomic design | Design systems / component libraries only | Ambiguous boundaries when applied to whole apps |
Default: feature-based. Atomic design belongs in a separate design-system package, not in your product app.
Place code as close to where it's relevant as possible.
X.test.tsx)X.module.css or Tailwind inline)useX.ts)_components/)# Barrel style
Button/
├── index.ts # re-exports Button
├── Button.tsx
├── Button.test.tsx
└── _components/
└── ButtonIcon.tsx
# Flat style
Button.tsx
Button.test.tsx
Decision rule:
index.ts files inside utils/ and components/ui/ — they hurt Next.js tree-shaking (vercel/next.js#92926)| Constant scope | Where |
|---|---|
| Used by one component, static | Module-level (top of component file, outside the function) |
| Used by multiple files in one feature | features/<feature>/constants.ts |
| Globally meaningful (routes, env keys, shared enums) | src/constants/ |
| Depends on props/state | Inline (computed in component) |
Never declare static constants inside the component function body — they're re-created on every render.
Pick one convention per project and document it. The most defensible split:
| Folder | What goes in | Example |
|---|---|---|
lib/ | Wrappers around external libraries; mini-packages (could be extracted as npm) | lib/axios.ts, lib/db.ts, lib/cn.ts |
utils/ | Pure, generic, project-agnostic functions | utils/format-date.ts, utils/range.ts |
services/ | Functions that do work (I/O, API calls, business actions) | services/billing.ts, services/auth.ts |
helpers/ | Avoid — overlaps with utils/. If used, restrict to project-specific glue |
utils/lib/services/Components render UI. Hooks own logic. Services do work. Components should not contain business logic.
View (presentational component)
↑ props
Container (wires hook + view)
↑ uses
Hook (logic, state, derived values)
↑ calls
Service / API layer (lib/, services/, or features/<f>/api/)
| Logic kind | Goes in |
|---|---|
| Stateful UI behavior (toggles, debounces, form state) | Custom hook |
| Client-side server-data fetching (React Query) | Custom hook wrapping a service |
| Server-side data fetching (RSC) | lib/ async fn or colocated with the route |
| Pure transform of input → output | utils/ |
| Side effect (network, storage, analytics) | services/ or lib/ |
| Cross-feature state (auth, theme) | Context + hook in lib/ or providers/ |
In Next.js App Router, server-side data fetching commonly lives inside the route segment (page.tsx) or in lib/ async functions. Client mutations + React Query still benefit from the hook layer.
Split a component when any of these is true:
Parent/_components/Sub.tsx (private folder)features/<f>/_components/src/components/UserCard.tsx)use-prefixed (useUser.ts)format-date.ts)auth-flow/), PascalCase only for component folders (UserCard/)Everything in app/ is one of:
page.tsx, layout.tsx, loading.tsx, error.tsx, route.ts, not-found.tsx, template.tsx_anything/ — excluded from routing(name)/ — affects organization, NOT the URLInside app/ only if it's used only by that segment:
app/(dashboard)/billing/
├── page.tsx
├── _components/InvoiceTable.tsx # used only by this route
└── _hooks/useInvoices.ts
Outside app/ if it's shared:
src/features/billing/ # shared by app/billing AND app/admin/billing
src/components/ui/ # generic UI used everywhere
Use route groups to share a layout across pages without nesting in the URL:
app/
├── (marketing)/ # public marketing pages
│ ├── layout.tsx # marketing layout
│ ├── page.tsx # /
│ └── pricing/page.tsx # /pricing
└── (app)/ # authenticated app
├── layout.tsx # app shell layout
└── dashboard/page.tsx # /dashboard
"use client" directive does"use client" as low in the tree as possible (leaves, not roots)asyncNEW FILE → WHAT IS IT?
├── React component
│ ├── Used by one route → app/<route>/_components/ (Next)
│ │ features/<f>/_components/ (Vite)
│ ├── Shared in one feature → features/<f>/_components/
│ └── Used across features → src/components/
│
├── Custom hook
│ ├── Used by one feature → features/<f>/hooks/
│ └── Generic → src/hooks/
│
├── Pure function
│ ├── Project-agnostic → src/utils/
│ └── Wraps an external lib → src/lib/
│
├── Function with I/O / side effects → src/services/ or features/<f>/api/
│
├── Constant
│ ├── Used by one file → top of that file (outside the component)
│ ├── Shared in one feature → features/<f>/constants.ts
│ └── Cross-feature → src/constants/
│
└── Type / DTO
├── Used by one feature → features/<f>/types.ts
└── Cross-feature → src/types/
For folder-tree examples (small Vite, mid-size Next, bulletproof-react style), see examples.md.
npx claudepluginhub yamchinsky/dev-digest-ai-marketplace --plugin engineering-paved-pathGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.