Skip to content

CLAUDE.md template for Next.js, from a real repo

A CLAUDE.md template for Next.js you can copy, a real one from a generated repo, where the file goes, what belongs in it, and the mistakes that get it ignored.

Updated · 10 min read

CLAUDE.md is a markdown file Claude Code reads at the start of every session. Put it at the root of your repo. Fill it with what Claude needs every time: commands, conventions, where things live, and what never to do. Keep it under 200 lines and push the rest into scoped rules and skills.

Below: where the file goes, a template to copy, and a real CLAUDE.md from a generated Next.js repo with 30 rules, 28 skills and 7 hooks behind it.

What is CLAUDE.md?

CLAUDE.md is persistent memory for Claude Code. You write it once. Claude reads it every session. You stop re-explaining the same things.

Three facts shape how you should write it:

  • It's plain markdown. No required fields. No schema. Headers and bullets.
  • It's context, not config. Anthropic's docs say Claude treats CLAUDE.md "as context, not enforced configuration." It arrives as a user message after the system prompt. Claude tries to follow it. Nothing forces it to.
  • It costs context every session. Every line loads, whether the task needs it or not. Longer files get followed less.

So CLAUDE.md is guidance. If something must never happen, you need a hook. More on that in the hooks guide.

Where to put CLAUDE.md

Put the project file at the repo root, as ./CLAUDE.md or ./.claude/CLAUDE.md. Commit it. That's the one your team shares.

Claude Code reads CLAUDE.md from four scopes, broadest first:

ScopeLocationUse it for
Managed policy/Library/Application Support/ClaudeCode/CLAUDE.md (macOS), /etc/claude-code/CLAUDE.md (Linux and WSL), C:\Program Files\ClaudeCode\CLAUDE.md (Windows)Company rules set by IT
User~/.claude/CLAUDE.mdYour preferences, in every project
Project./CLAUDE.md or ./.claude/CLAUDE.mdTeam rules, committed to git
Local./CLAUDE.local.mdYour notes for this one project. Add it to .gitignore

How they load:

  • Files in your working directory and every folder above it load at launch.
  • Files in subfolders load on demand, when Claude reads a file in that subfolder.
  • Nothing overrides anything. Every file found is concatenated, root first. The file closest to where you launched is read last.
  • In each folder, CLAUDE.local.md comes after CLAUDE.md.

To check what loaded, run /context and look under Memory files. /memory lists every location and opens the file in your editor.

What goes in a CLAUDE.md

Anthropic's rule of thumb: facts Claude should hold in every session. Build commands, conventions, project layout and "always do X" rules. Add a line when:

  • Claude makes the same mistake a second time.
  • A code review catches something Claude should have known.
  • You type the same correction you typed last session.
  • A new teammate would need the same context.

Not everything belongs in the file. Here's where each kind of instruction goes:

ContentWhere it goes
Install, dev, test, typecheck and lint commandsCLAUDE.md
Repo-wide conventions (exports, imports, naming)CLAUDE.md, or a rule with no paths
Rules for one part of the code (webhooks, schema, components).claude/rules/*.md with paths:
Multi-step procedures (add a table, ship a release)A skill in .claude/skills/. See the skills guide
Things that must never happen (rm -rf, secrets in output)A hook. See the hooks guide
Your personal preferences~/.claude/CLAUDE.md or CLAUDE.local.md
Directory trees, dependency lists, architecture toursNowhere. Claude can read the code

That last row matters. Claude Code's /doctor checkup proposes cutting exactly that: content Claude can work out from the codebase. It keeps pitfalls, the reasons behind decisions, and conventions that differ from tool defaults.

CLAUDE.md template (copy this)

A starting template for a Next.js App Router repo. We wrote it as a skeleton for this page, not from a real project. Swap in your own commands, paths and rules.

# my-app

Next.js App Router on Vercel. TypeScript strict. Postgres through Drizzle.

## Commands

- `pnpm dev`: local dev server
- `pnpm typecheck`: run before you say a task is done
- `pnpm lint`: formatting is the linter's job. Accept its output.
- `pnpm test`: unit tests

## Where things live

- `src/app/`: routes. Server Components unless a file needs state or effects.
- `src/lib/`: server code. Never import it into a "use client" file.
- `src/db/schema.ts`: the schema. Every change ships with a generated migration.

## Always

- Branch before you commit: `feat/<slug>` or `fix/<slug>`.
- Read env vars through `src/lib/env.ts`, never `process.env` in feature code.
- Only `NEXT_PUBLIC_` variables in client code.
- Parse every request body with Zod before you use it.

## Never

- Never commit `.env.local` or print a secret.
- Never add a dependency without saying why.

## More context

- Setup and env vars: @docs/onboard.md
- Path-scoped rules live in `.claude/rules/`.

Two details in that last section:

  • @docs/onboard.md is an import. Claude Code expands it into context at launch.
  • The backticked .claude/rules/ is plain text. Import parsing skips code spans and code blocks.

A real CLAUDE.md from a generated Next.js repo

This is the CLAUDE.md the generator writes for the Indie SaaS preset: Next.js on Vercel with Better Auth, Neon, Drizzle, Stripe, Resend, PostHog, Sentry, an admin panel and an MDX blog. It comes straight from a real generate run. Nobody retyped it.

# my-app

Generated by [Agentic Boilerplate](https://github.com/agentic-studio/agentic-boilerplate) from [Agentic Studio](https://theagentic.studio). Same `agentic.config.json`, same repo: regenerate and diff any time.

- **Stack:** Next.js on Vercel (`nextjs-vercel`)
- **Batteries:** Drizzle ORM (`drizzle`), Neon (`neon`), Better Auth (`better-auth`), Stripe (`stripe`), Resend (`resend`), Sentry (`sentry`), PostHog (`posthog`), Admin panel (`admin-panel`), MDX blog (`blog-mdx`)
- **Design:** Daylight (`daylight`). See [DESIGN.md](DESIGN.md).
- **Package manager:** bun
- **Mode:** solo
- **Agent targets:** claude, codex, cursor

## Read this first

On a fresh clone, read [docs/onboard.md](docs/onboard.md) before running or
editing anything. It lists every environment variable, where to get it, and
the order to set the services up.

```sh
bun install
cp .env.example .env.local
bun run verify
bun run dev
```

## How this repo is set up for agents

- `.claude/rules/`: 30 rules. 4 load every session, 26 load when you read a file they cover.
- `.claude/agents/`: 7 subagents, listed below.
- `.claude/skills/`: 28 skills, listed below.
- `.claude/hooks/`: 7 guard hooks, wired in `.claude/settings.json` for Claude Code.
- `.mcp.json`: 5 MCP servers (`better-auth`, `neon`, `posthog`, `sentry`, `stripe`). Setup is in [docs/onboard.md](docs/onboard.md).
- `docs/solutions/`: 74 solved problems. Read the relevant one before re-solving anything.
- `docs/plans/`: one plan per unit of work.

Run `bun run verify:hooks` to prove the guards still block what they claim to block.
Do not edit `.claude/settings.json` by hand: the `system-manager` agent owns it.

## Workflow

The Compound Engineering plugin adds the loop: `/ce-brainstorm`, `/ce-plan`, `/ce-work`, `/ce-code-review`, `/ce-compound`.
`.claude/settings.json` enables it once you trust this folder. If the commands are missing, run `/plugin install compound-engineering@compound-engineering-plugin`.

## Rules

Loaded every session:

- [Code style and file conventions](.claude/rules/code-style.md)
- [Git and change hygiene](.claude/rules/git.md)
- [Security rules](.claude/rules/security.md)
- [No personal data in breadcrumbs, tags or extra](.claude/rules/sentry-no-pii.md)

Loaded when you read a file they cover:

| Rule | Applies to |
|---|---|
| [Admin pages check the role themselves and read data on the server](.claude/rules/admin-access.md) | `src/app/(admin)/**`, `src/components/admin/**`, `src/lib/admin/actions.ts`, `src/app/api/admin/**` |
| [Admin writes go through the provider port, and every one is audited](.claude/rules/admin-mutations.md) | `src/lib/admin/**`, `src/components/admin/**`, `scripts/admin/**` |
| [Pages in the signed-in app](.claude/rules/app-shell.md) | `src/app/(app)/**`, `src/components/app/**`, `src/components/ui/sidebar.tsx`, `src/lib/app-shell.ts`, `src/lib/nav.ts` |

First 58 of 134 lines of CLAUDE.md.

What it gets right:

  • The header is one line per fact. Stack, batteries, design, package manager, mode, agent targets. Claude knows what it's working with before it opens a file.
  • "Read this first" points at one doc. docs/onboard.md holds every env var and the setup order. CLAUDE.md doesn't repeat it.
  • It's an index, not an encyclopedia. It counts the rules, subagents, skills, hooks, MCP servers and solution docs, then links to them. The rule text lives in .claude/rules/.
  • It says what loads when. A few rules load every session. The rest load when Claude reads a file they cover, and the table maps each rule to its globs.
  • It names the guard. The hooks are wired in .claude/settings.json, and bun run verify:hooks proves they still block.

The rest of the file (not shown) is two tables: every skill and every subagent, one line each. The whole file stays under Anthropic's 200-line target. It can, because the heavy content lives somewhere else.

Move scoped rules into .claude/rules

A CLAUDE.md gets long when every rule lives in it. The fix is .claude/rules/.

  • Each .md file in .claude/rules/ is one rule. Subfolders work. Files are found recursively.
  • A rule with no paths loads at launch, with the same priority as .claude/CLAUDE.md.
  • A rule with paths: frontmatter loads only when Claude uses Read, Write or Edit on a matching file.
  • paths is the only frontmatter field Claude Code reads from a rule. Anything else is ignored.

Here is a scoped rule from the same repo. It loads when Claude touches the Stripe webhook route or the billing pipeline. Editing a marketing page never pulls it in.

---
paths:
  - src/app/api/webhooks/stripe/**
  - src/lib/billing/provider.ts
  - src/lib/billing/webhook.ts
---

# Verify every Stripe webhook, keep every handler idempotent

The webhook route is an unauthenticated public endpoint. The signature is the
only thing between a Stripe event and a forged POST that grants a lifetime
plan.

The route is three lines: `processWebhook(billingProvider, request)`. The
pipeline in `src/lib/billing/webhook.ts` is shared by every provider, and the
Stripe parts are `verifyWebhook` and `translate` in `provider.ts`. Keep it that
way: nothing Stripe-specific in the route.

**Read the body as text.** `processWebhook` calls `request.text()` and hands
those exact bytes to `verifyWebhook`. `request.json()` reorders keys and every
signature check fails. Never add a body parser or middleware in front of it.

First 21 of 71 lines of .claude/rules/stripe-webhook-integrity.md.

The rule names real functions and real files. Further down it names the status codes that drive Stripe's retries. That's what makes it checkable. The full Stripe battery is at /with/stripe.

Personal rules can live in ~/.claude/rules/. They load before project rules and apply to every project on your machine.

How @imports work in CLAUDE.md

Write @path/to/file anywhere in CLAUDE.md and Claude Code pulls that file in at launch.

  • Relative paths resolve from the file that holds the import, not from your working directory.
  • Absolute paths and ~/ paths work too.
  • Imported files can import more files, up to four hops deep.
  • Paths inside backticks or code blocks are not imported.
  • The first time a project imports a file outside the working directory, Claude Code asks you to approve it.

One catch. Imports organize a file. They don't shrink it. Imported files load at launch too, so they cost the same context. To actually save context, use path-scoped rules.

The most useful import is @AGENTS.md. It lets Claude Code and Codex share one file. See CLAUDE.md vs AGENTS.md.

CLAUDE.md best practices

PracticeWhy
Keep each file under 200 linesAnthropic's target. Longer files use more context and get followed less
Write checkable lines"Use 2-space indentation" beats "format code properly"
Group under headers and bulletsEasier to follow than dense paragraphs
Give each fact one homeIf two lines contradict, Claude may pick either one
Scope rules with paths:A billing rule has no business loading for a CSS fix
Turn procedures into skillsSkills load only when invoked or relevant
Turn hard stops into hooksA PreToolUse hook blocks a tool call no matter what Claude decides
Leave maintainer notes in HTML commentsBlock-level <!-- --> comments are stripped before Claude sees them
Check what loaded with /contextA file missing from Memory files isn't being read
Prune it when the code changesDead paths and old commands teach Claude wrong things

Common CLAUDE.md mistakes

  • Pasting the README. Setup prose, badges, a directory tree. Claude can read the tree itself.
  • Vague advice. "Write clean code" can't be checked. "Named exports only, except page.tsx and layout.tsx" can.
  • One giant file. Forty rules in CLAUDE.md means forty rules on every task, relevant or not.
  • Trusting it to stop damage. CLAUDE.md can say "never run git reset --hard". Only a hook can refuse it. The example repo ships 7 guard hooks for that.
  • "Read AGENTS.md" written in words. Claude sees the file only if it decides to open it. Write @AGENTS.md instead.
  • Personal notes in the team file. Your sandbox URLs go in CLAUDE.local.md, gitignored.
  • Secrets. CLAUDE.md is committed. Never put a key in it, not even a test key.
  • Fighting your own rules. CLAUDE.md says one thing, .claude/rules/testing.md says another. Claude picks one, and it may not be yours.

Generate a CLAUDE.md: /init or a generator

Two ways to skip the blank page.

/init in Claude Code. It reads your codebase and writes a starting CLAUDE.md with the build commands, test instructions and conventions it finds. If a CLAUDE.md already exists, it suggests improvements instead of overwriting. It also reads Cursor rules and .github/copilot-instructions.md and folds in the useful parts.

Agentic Boilerplate. Pick your batteries at /build. You get a Next.js repo with a CLAUDE.md written for that stack, plus everything it points to. For the Indie SaaS preset that's 30 path-scoped rules, 28 skills, 7 subagents, 7 guard hooks and 74 solution docs, all of them public in the cookbook. Free during launch, then $99 once. How the pieces fit: the agentic layer.

From a terminal: npm create agentic-boilerplate@latest my-app.

Use /init for a repo you already have. Use the generator for a new one.

Keep going

FAQ

Where do I put CLAUDE.md?

At the root of your repo, as ./CLAUDE.md or ./.claude/CLAUDE.md, and commit it. Personal rules for every project go in ~/.claude/CLAUDE.md. Private notes for one project go in CLAUDE.local.md, added to .gitignore.

How long should a CLAUDE.md file be?

Anthropic's docs say to target under 200 lines per file. Longer files use more context and get followed less. Move anything that only matters for part of the code into .claude/rules/ with paths:.

Does Claude Code read AGENTS.md?

Yes, from v2.1.277, when there's no CLAUDE.md or CLAUDE.local.md in your working directory or above it. If both files exist, Claude reads CLAUDE.md only by default. Put @AGENTS.md in your CLAUDE.md to load both.

Can CLAUDE.md import other files?

Yes. Write @path/to/file. Paths resolve from the importing file, imports can nest four hops deep, and imported files load at launch, so they don't save context.

Does Claude always follow CLAUDE.md?

No. Claude treats it as context, not enforced configuration. For anything that must never happen, use a PreToolUse hook, which runs before the tool call and can block it.

Is there a CLAUDE.md generator?

Claude Code's /init writes a starter CLAUDE.md from your existing code. For a new Next.js project, Agentic Boilerplate writes CLAUDE.md together with the rules, skills, subagents and hooks it indexes.

Sources

Tool behavior is from the official docs, checked on October 4, 2026. Tools change. The docs win.