# The Claude Code setup for a Next.js app

> The best Claude Code setup for a Next.js repo: a short CLAUDE.md, path-scoped rules, skills, subagents, guard hooks and MCP. What goes where, with real files.

*Updated 2026-10-04.*

A good Claude Code setup is mostly about where each instruction lives. Facts Claude needs on every task go in `CLAUDE.md`. Conventions for one folder go in a path-scoped rule. Procedures go in skills. Narrow jobs go to subagents. Anything that must never happen goes in a hook.

Get the placement right and your agent forgets less. Get it wrong and you get a 600-line `CLAUDE.md` it half-reads.

This page is the whole setup on one page, with real files from a generated Next.js repo. Each section links to a deeper guide.

## The setup at a glance

| Layer | Where | When it loads | Use it for | Guide |
|---|---|---|---|---|
| `CLAUDE.md` | Repo root | Every session, in full | Stack, commands, layout, pointers | [CLAUDE.md template](/guides/claude-md-template) |
| Rules | `.claude/rules/*.md` | Every session, or when Claude touches a matching file | Conventions per folder | This page |
| Skills | `.claude/skills/<name>/SKILL.md` | Description always, body when used | Repeated procedures | [Skills](/guides/claude-code-skills) |
| Subagents | `.claude/agents/*.md` | When spawned, in their own context | Reviewers, auditors, read-only roles | [Subagents](/guides/claude-code-subagents) |
| Hooks | `.claude/settings.json` + scripts | On the event. No context cost | Things that must never happen | [Hooks](/guides/claude-code-hooks) |
| MCP servers | `.mcp.json` | Tool names at start | Talking to Stripe, Neon, Sentry | This page |
| Solution docs | `docs/solutions/` | When read | Known mistakes, written down once | This page |

The last row is not a Claude Code feature. It is a folder of markdown files and a line in `CLAUDE.md` that says "read the relevant one first". It works anyway.

## The file tree

This is the shape of a repo the generator writes:

```
my-app/
  CLAUDE.md                  # the index Claude reads every session
  AGENTS.md                  # the same rules for Codex
  .claude/
    settings.json            # hooks and plugins
    rules/                   # path-scoped conventions
    skills/                  # /slash-command procedures
    agents/                  # subagents
    hooks/                   # guard scripts
  .cursor/rules/             # the rules again, for Cursor
  .mcp.json                  # MCP servers for your batteries
  docs/
    onboard.md               # every env var and where to get it
    solutions/               # known problems, solved
    plans/                   # one plan per piece of work
  src/
```

Commit `.claude/`, except `settings.local.json`. Personal tweaks go there and in `CLAUDE.local.md`.

## 1. Keep CLAUDE.md short

`CLAUDE.md` loads in full on every request. Anthropic's docs say to target under 200 lines. Longer files cost more context and get followed less.

What belongs in it:

- The stack and the package manager.
- The four commands to get running.
- Where things live.
- Pointers to everything else: rules, skills, subagents, `docs/onboard.md`.

What does not:

- Conventions for one folder. Those are rules.
- Multi-step procedures. Those are skills.
- "Never run X." That is a hook.

`@path` imports help you organize, but imported files still load at launch. They don't save context.

The generated `CLAUDE.md` is an index, not a manual. It lists the stack, four setup commands and the counts, then every rule, skill and subagent with a one-line summary. The full walkthrough is in the [CLAUDE.md template](/guides/claude-md-template) guide.

If you also run Codex, keep an `AGENTS.md`. When a repo has both files, Claude Code reads `CLAUDE.md` by default. The generator writes both. See [CLAUDE.md vs AGENTS.md](/guides/claude-md-vs-agents-md).

## 2. Path-scoped rules

A rule is a markdown file in `.claude/rules/`. Without frontmatter it loads at session start, like `CLAUDE.md`. Add a `paths` list and it loads only when Claude reads, writes or edits a matching file.

That is the trick that keeps a big setup cheap. A rule on `src/lib/billing/**` costs nothing while Claude edits a marketing page.

### Copy this: a path-scoped rule

A generic example. Save as `.claude/rules/route-handlers.md`:

```markdown
---
paths:
  - "src/app/api/**/route.ts"
---

# Route handlers

- Parse the request body with a Zod schema before you use it.
- Check the session inside the handler. Never rely on proxy.ts alone.
- Return Response.json(...) with an explicit status code.
- A new handler gets a test for the happy path and the unauthorized path.
```

How rules behave:

- **`paths` is the only field Claude Code reads.** Anything else in the frontmatter is ignored.
- **Globs work as you expect.** `src/**/*.tsx`, `src/components/**`, `*.{ts,tsx}`.
- **Quote globs that start with `*` or `{`.** YAML reads a bare `*` as an alias. If the frontmatter fails to parse, Claude Code ignores it and loads the rule everywhere.
- **Subfolders work.** All `.md` files under `.claude/rules/` are found, so `rules/frontend/` and `rules/backend/` are fine.
- **Personal rules** go in `~/.claude/rules/` and apply to every project.

### A real rule, scoped to the files it governs

This is the deployment rule from a generated Next.js repo. It loads when Claude touches `next.config.ts`, `src/proxy.ts`, a route handler or `.env.example`:

````markdown
---
paths:
  - next.config.ts
  - vercel.json
  - package.json
  - src/proxy.ts
  - src/app/**/route.ts
  - .env.example
---

# Deployment rules

Target is Vercel. These constraints are what actually breaks builds and
runtimes, in the order they usually break them.

## Before any deploy

Run all four locally and get them green:

```bash
bun run typecheck
bun run lint
bun run test
bun run build
```

A green dev server is not evidence. `next build` type-checks and prerenders
paths that `next dev` never touches.
````

*First 28 of 72 lines of `.claude/rules/deployment.md`.*

The full repo ships 30 rules. Each line shows the paths that load it:

- `admin-access`: `src/app/(admin)/**`, `src/components/admin/**`, `src/lib/admin/actions.ts`, `src/app/api/admin/**`
- `admin-mutations`: `src/lib/admin/**`, `src/components/admin/**`, `scripts/admin/**`
- `app-shell`: `src/app/(app)/**`, `src/components/app/**`, `src/components/ui/sidebar.tsx`, `src/lib/app-shell.ts`, `src/lib/nav.ts`
- `auth-server-boundary`: `src/lib/auth/**`, `src/app/api/auth/**`, `src/app/(better-auth)/**`, `src/components/auth/**`
- `billing-core`: `src/lib/pricing.ts`, `src/lib/billing/**`, `src/app/pricing/**`, `src/app/(app)/billing/**`, `src/components/billing/**`
- `blog-content`: `content/**`
- `blog-rendering`: `src/app/blog/**`, `src/app/sitemap.ts`, `src/lib/blog/**`, `src/components/blog/**`, `src/mdx-components.tsx`
- `code-style`: always loaded
- `deployment`: `next.config.ts`, `vercel.json`, `package.json`, `src/proxy.ts`, `src/app/**/route.ts`, `.env.example`
- `drizzle-migrations`: `src/db/**`, `drizzle/**`, `drizzle.config.ts`
- `drizzle-schema`: `src/db/**`
- `email-sending-discipline`: `src/lib/email/**`, `src/app/api/webhooks/resend/**`, `src/lib/auth/**`, `src/lib/billing/**`
- `event-naming`: `src/lib/analytics/**`, `src/app/**`, `src/components/**`
- `git`: always loaded
- `identify-timing`: `src/lib/analytics/**`, `src/app/**`, `src/components/**`
- `landing-and-legal`: `src/lib/site.ts`, `src/lib/llms.ts`, `src/app/page.tsx`, `src/app/(legal)/**`, `src/app/llms.txt/**`, `src/components/marketing/**`, `src/components/site/**`
- `neon-connections`: `src/db/**`, `src/app/api/**`
- `neon-migrations`: `src/db/**`
- `roles-are-server-side`: `src/app/**`, `src/components/**`, `src/lib/auth/**`
- `security`: always loaded
- `sentry-capture`: `src/**`, `sentry.server.config.ts`, `sentry.edge.config.ts`
- `sentry-no-pii`: always loaded
- `server-truth-and-pii`: `src/lib/analytics/**`, `src/app/**`, `src/components/**`
- `stripe-billing-store`: `src/lib/billing/**`, `scripts/billing/**`
- `stripe-pricing-source-of-truth`: `src/lib/pricing.ts`, `src/lib/billing/**`, `scripts/billing/**`
- `stripe-server-boundary`: `src/lib/billing/**`, `src/app/api/webhooks/stripe/**`, `src/app/**`
- `stripe-webhook-integrity`: `src/app/api/webhooks/stripe/**`, `src/lib/billing/provider.ts`, `src/lib/billing/webhook.ts`
- `testing`: `tests/**`, `src/**/*.test.ts`, `src/**/*.test.tsx`
- `tokens-only`: `src/components/**`, `src/app/**`
- `ui-kit`: `src/components/**`, `src/app/**`

Seven come from the Next.js stack: `code-style`, `git` and `security` load every session, and `testing`, `deployment`, `ui-kit` and `landing-and-legal` load for the files they cover. `app-shell`, `billing-core` and `tokens-only` come with auth, payments and the design. The rest come from the batteries. Stripe alone adds four.

The same rules compile to 58 Cursor files (rules plus one per skill). Each keeps the scope as `globs`:

````markdown
---
alwaysApply: false
description: Deployment rules
globs: next.config.ts,vercel.json,package.json,src/proxy.ts,src/app/**/route.ts,.env.example
---
````

*First 5 of 66 lines of `.cursor/rules/deployment.mdc`.*

More on that in [Cursor rules for Next.js](/guides/cursor-rules-nextjs).

### Write rules Claude can check

- **Checkable, not vibes.** "Re-read the files you touched before you finish" works. "Write clean code" doesn't.
- **Do, don't, exception.** In that order.
- **One topic per file.** `stripe-webhook-integrity.md`, not `backend.md`.
- **Short.** The generated `system-manager` agent caps rules at roughly 40 lines. Longer than that, it's a solution doc.
- **Scoped by default.** An unscoped rule costs context on every task. Make it earn that.

## 3. Skills for repeated work

A skill is a `SKILL.md` that becomes a slash command. Claude sees only its description until it runs, so 30 skills cost 30 descriptions, not 30 files.

The generated repo ships 28: `/verify`, `/write-spec`, `/qa-feature`, `/deploy-to-vercel` and `/security-audit` from the stack, plus battery ones like `/add-plan`, `/test-webhook`, `/db-branch` and `/add-table`.

Write one the third time you explain the same procedure. Full guide, with the `/verify` skill quoted in full: [Claude Code skills](/guides/claude-code-skills).

## 4. Subagents for narrow jobs

A subagent is a separate Claude with its own prompt, tools and context window. It hands back a summary.

The generated repo ships 7. `pr-reviewer` reviews a diff against `.claude/rules/`. `security-auditor` hunts leaked keys and missing auth checks. `db-inspector` runs `SELECT` and `EXPLAIN` only. `system-manager` owns `.claude/` and turns repeated corrections into rules.

The rule of thumb: give each one the smallest tool list that does the job. Full guide: [Claude Code subagents](/guides/claude-code-subagents).

## 5. Hooks for what must never happen

Rules, skills and `CLAUDE.md` are all instructions. Claude reads them and decides. A hook is a script Claude Code runs on every matching tool call, whatever Claude decides.

A `PreToolUse` hook that exits 2 blocks the call. Hooks run before permission checks, so a block holds even with `--dangerously-skip-permissions`. The generated repo wires 7:

- `auto-lint.ts`
- `block-destructive.ts`
- `enforce-doc-meta.ts`
- `enforce-typecheck.ts`
- `env-leak-detector-write.ts`
- `env-leak-detector.ts`
- `guard-neon-sql.ts`

Together they block `rm -rf`, force pushes, `DROP TABLE` and `.env` reads, and redact live secrets from output. A self-test, `bun run verify:hooks`, proves each one still fires. Full guide with the wiring: [Claude Code hooks](/guides/claude-code-hooks).

## 6. MCP servers, only the real ones

MCP servers give Claude tools for outside services. Project servers live in `.mcp.json` at the repo root, committed so the team gets the same ones. In an interactive session, Claude Code asks for approval before it uses a project server.

The generated repo only lists servers that its batteries actually have:

```json
{
  "mcpServers": {
    "better-auth": {
      "type": "http",
      "url": "https://mcp.better-auth.com/mcp"
    },
    "neon": {
      "type": "http",
      "url": "https://mcp.neon.tech/mcp?readonly=true"
    },
    "posthog": {
      "type": "http",
      "url": "https://mcp.posthog.com/mcp?readonly=true"
    },
    "sentry": {
      "type": "http",
      "url": "https://mcp.sentry.dev/mcp"
    },
    "stripe": {
      "type": "http",
      "url": "https://mcp.stripe.com"
    }
  }
}
```

*`.mcp.json`, as generated.*

Neon and PostHog connect read-only (`?readonly=true`). Sign in to each with `/mcp`. Don't add a server you won't use. Every one is another login and another set of tools in the list.

## 7. Solution docs: mistakes written down once

`docs/solutions/` holds one problem per file: symptom, cause, fix, how to verify. The example repo is seeded with 74, like idempotent Stripe webhooks, Neon pooled vs direct URLs, and the PostHog identify race.

`CLAUDE.md` tells Claude to read the relevant one before re-solving anything. When you fix something new, write it down. Every seeded doc is public in [the cookbook](/cookbook). Start with [idempotent Stripe webhooks](/cookbook/stripe/idempotent-stripe-webhooks).

## Claude Code best practices for a Next.js repo

| Do | Why |
|---|---|
| Keep `CLAUDE.md` under 200 lines | It loads on every request |
| Scope every folder-specific rule with `paths` | It loads only when it applies |
| Name your Next.js, React and TypeScript majors in a rule | Models trained on older code write older APIs |
| Write rules for `route.ts`, `proxy.ts` and `next.config.ts` | That is where builds and deploys break |
| Turn a procedure you explained twice into a skill | It costs one line until used |
| Gate side-effect skills with `disable-model-invocation: true` | No surprise deploys |
| Give every subagent an explicit `tools` list | Leaving it out grants every tool |
| Put "never do X" in a `PreToolUse` hook | Instructions are requests, hooks are not |
| Use `"$CLAUDE_PROJECT_DIR"` in hook commands | Guards keep firing after `cd` |
| Test hooks after every change to `.claude/` | Guards die without telling you |
| Commit `.claude/` and `.mcp.json` | The whole team gets the same agent |
| Turn a correction you made twice into a rule | Two is a pattern, one is an accident |

The generated `code-style` rule has a section for this: "Examples online often target older majors. These are the ones installed here." Copy the idea even if you copy nothing else.

## Common mistakes

- **The 600-line `CLAUDE.md`.** Everything in one file, all of it loaded on every task, half of it ignored.
- **Unscoped rules for everything.** Billing rules loading while Claude edits a button.
- **Advice instead of rules.** "Be careful with webhooks" gives Claude nothing to check.
- **Guardrails as prose.** "Never run `git reset --hard`" in `CLAUDE.md` is a wish.
- **Subagents with every tool.** The read-only reviewer that can edit.
- **Hooks nobody tested.** Wired once, broken since the last refactor.
- **Rules that contradict.** Claude picks one at random. Audit `CLAUDE.md` and `.claude/rules/` together.
- **A setup that never changes.** If corrections don't turn into rules, the same bug gets fixed twice.

## Get the whole setup in one command

That is a lot of files to write by hand. The generator writes them for your stack:

```bash
npm create agentic-boilerplate@latest my-app
```

Or click through the [builder](/build). Pick from 26 batteries (auth, database, payments, email, analytics, admin, AI) and 31 designs. The [Indie SaaS preset](/stack/indie-saas) gives you 30 rules, 28 skills, 7 subagents, 7 hooks and 74 solution docs. Rules and skills compile for Claude Code, Codex and Cursor. Free during launch, then $99 once.

Battery pages show what each one adds: [Stripe](/with/stripe), [Neon](/with/neon). How the layers fit together: [the agentic layer](/docs/the-agentic-layer). The Codex side: [AGENTS.md examples](/guides/agents-md-examples).

## FAQ

### What is the best Claude Code setup for a Next.js project?

A short `CLAUDE.md` as an index, path-scoped rules in `.claude/rules/` for each part of the app, skills for repeated procedures, a few subagents with narrow tool lists, and `PreToolUse` hooks for anything destructive. Commit all of it.

### What are path-scoped rules in Claude Code?

Markdown files in `.claude/rules/` with a `paths` list of globs in their frontmatter. They load only when Claude reads, writes or edits a matching file, so they cost no context the rest of the time.

### Where do Claude Code rules go?

Project rules go in `.claude/rules/` and get committed. Personal rules go in `~/.claude/rules/` and apply to every project on your machine.

### How long should CLAUDE.md be?

Anthropic's docs say to target under 200 lines. Move folder-specific conventions into path-scoped rules and procedures into skills.

### Does Claude Code read AGENTS.md?

Recent versions read `AGENTS.md` when there is no `CLAUDE.md`. When both exist, Claude Code reads `CLAUDE.md` by default, and a `CLAUDE.md` can pull in `AGENTS.md` with an `@AGENTS.md` import.

### Should I commit the .claude folder?

Yes. Commit `.claude/settings.json`, rules, skills, agents and hooks so the team gets the same setup. Keep personal settings in `.claude/settings.local.json`.


## Sources

- [Claude Code docs: How Claude remembers your project](https://code.claude.com/docs/en/memory)
- [Claude Code docs: Extend Claude Code](https://code.claude.com/docs/en/features-overview)
- [Claude Code docs: Hooks reference](https://code.claude.com/docs/en/hooks)
- [Claude Code docs: MCP](https://code.claude.com/docs/en/mcp)

## Generate it

[Build your repo](https://agenticboilerplate.com/build)

---

Agentic Boilerplate: A Next.js repo your agent already knows. Free during launch, then $99 once.

- Site map for agents: https://agenticboilerplate.com/llms.txt
- Public API: https://agenticboilerplate.com/openapi.json
- Contact: agenticstudio@gmail.com
