A good CLAUDE.md is specific, actionable, and tailored to your project. A bad one is generic, long, and full of best practices that Claude Code already knows without being told.
This guide gives you five complete CLAUDE.md templates for real project types. Copy the structure, fill in your specifics, and delete anything that does not apply.
What Makes a CLAUDE.md Effective
Three qualities separate a CLAUDE.md that improves output from one that just adds noise:
Specific. “Use Express 4.18 with CommonJS” is specific. “Use modern JavaScript best practices” is not. Claude Code already knows best practices. It does not know your specific choices unless you tell it.
Actionable. Every instruction should describe a behavior Claude Code can actually follow. “Write clean code” is not actionable. “All functions must have JSDoc comments with @param and @returns” is actionable.
Project-specific. If the instruction is true for every Node.js project, it probably belongs in your global CLAUDE.md or not at all. Project CLAUDE.md should contain only what is specific to this project.
The test for any CLAUDE.md instruction: would Claude Code get this wrong without the instruction? If yes, include it. If no, skip it.
Example 1: Node.js REST API
This template covers a backend API project using Express, PostgreSQL, and Jest.
# orders-api
REST API for order management. Handles order creation, fulfillment status,
and customer notifications.
## Stack
- Node.js 20 (LTS)
- Express 4.18
- PostgreSQL 15 via node-postgres (pg), no ORM
- Jest 29 + Supertest for testing
- ESLint with Airbnb config (enforced in CI)
## Conventions
- CommonJS only (require/module.exports), no ESM
- Route handlers in src/routes/, one file per resource
- Business logic in src/services/, database queries in src/db/queries/
- HTTP responses: always return { data: ... } on success, { error: string, code: string } on error
- All database queries are parameterized (no string interpolation)
- Input validation with Joi before any database call
## Testing
- Unit tests: tests/unit/ (mock the database)
- Integration tests: tests/integration/ (use test database)
- Run: npm test
- New routes require integration tests. New service functions require unit tests.
- Test database URL: TEST_DATABASE_URL env var
## Do Not Touch
- .env and .env.example
- src/db/migrations/ (use npm run migrate to create new migrations)
- package-lock.json (run npm ci, not npm install)
## File Structure
- Entry point: src/server.js
- Routes: src/routes/
- Services: src/services/
- DB queries: src/db/queries/
- Middleware: src/middleware/
- Utilities: src/utils/
## External Services
- Stripe for payments: src/services/billing.js (STRIPE_SECRET_KEY env var)
- SendGrid for email: src/services/email.js (SENDGRID_API_KEY env var)
- Never hardcode API keys or secrets
## Setup
- npm ci
- cp .env.example .env (fill in values)
- npm run migrate
- npm run dev
Why each section matters: The “Conventions” section eliminates the most common mistakes: ESM/CommonJS mismatch, inconsistent response shapes, and unsanitized database queries. The “Do Not Touch” section protects migrations, which are the highest-risk files in a database-backed project. The “Testing” section tells Claude Code which test type to write for which code.
Example 2: Python FastAPI Service
This template covers a Python microservice with FastAPI, SQLAlchemy, and pytest.
# user-service
Microservice handling user registration, authentication, and profile management.
Part of the platform monorepo; communicates via REST with other services.
## Stack
- Python 3.11
- FastAPI 0.110
- SQLAlchemy 2.0 (async) with asyncpg
- Pydantic v2 for request/response models
- pytest + pytest-asyncio for testing
- Alembic for migrations
- Ruff for linting and formatting
## Conventions
- Type hints required on all function signatures (enforced by mypy in CI)
- Pydantic models for all request bodies and response shapes (in app/schemas/)
- SQLAlchemy models in app/models/, one file per domain entity
- Route handlers in app/routers/, business logic in app/services/
- All database operations must be async (use async with get_db())
- Raise HTTPException for client errors (4xx), let middleware handle 500s
- Use snake_case for everything: files, functions, variables
## Testing
- Tests: tests/
- Run: pytest
- Unit tests mock the database session (use pytest fixtures in tests/conftest.py)
- Integration tests use a test database (TEST_DATABASE_URL)
- 80% coverage minimum enforced in CI
## Do Not Touch
- alembic/versions/ (generate with: alembic revision --autogenerate -m "description")
- .env and .env.example
- pyproject.toml dependency pins without confirming compatibility
## File Structure
- Entry point: app/main.py
- Routers: app/routers/
- Services: app/services/
- Models (DB): app/models/
- Schemas (Pydantic): app/schemas/
- Dependencies: app/dependencies.py
## External Services
- JWT tokens: python-jose library (SECRET_KEY env var)
- Redis for session storage: app/cache.py (REDIS_URL env var)
## Setup
- python -m venv venv && source venv/bin/activate
- pip install -e ".[dev]"
- cp .env.example .env
- alembic upgrade head
- uvicorn app.main:app --reload
Why each section matters: Python projects have more opportunity for type inconsistency than JavaScript projects. Specifying “type hints required” and “Pydantic v2 for all request/response models” prevents Claude Code from writing untyped functions or using dict instead of Pydantic models for response shapes.
Example 3: Next.js Frontend
This template covers a Next.js 14+ App Router project with Tailwind CSS and shadcn/ui.
# dashboard-app
Customer dashboard for account management and analytics visualization.
Built with Next.js App Router.
## Stack
- Next.js 14 (App Router, not Pages Router)
- TypeScript 5.3 (strict mode)
- Tailwind CSS 3.4
- shadcn/ui for components (built on Radix UI)
- React Query (TanStack Query v5) for data fetching
- Zod for validation
- Vitest + React Testing Library for tests
## Conventions
- App Router only: all routes in app/ directory, no pages/
- Server Components by default; use "use client" only when necessary
- shadcn/ui components in components/ui/ (do not modify these files)
- Custom components in components/ with a .tsx extension
- No inline styles; use Tailwind classes only
- Data fetching in Server Components or via React Query hooks in components/hooks/
- All API calls go through lib/api.ts, not directly from components
- Zod schemas in lib/schemas/ for all form validation
## Testing
- Tests: __tests__/
- Run: npm test
- Component tests use React Testing Library (not Enzyme)
- Test user behavior, not implementation details
## Do Not Touch
- components/ui/ (shadcn/ui generated files, update via CLI: npx shadcn@latest add)
- next.config.ts (discuss before modifying)
- tailwind.config.ts theme section (discuss before extending)
## File Structure
- App routes: app/
- Components: components/
- Hooks: components/hooks/
- Utilities: lib/
- Types: types/
- API layer: lib/api.ts
## Environment
- NEXT_PUBLIC_API_URL: backend API base URL
- Run dev server: npm run dev (port 3000)
Why each section matters: The single most important instruction here is “App Router only.” Claude Code may default to Pages Router patterns because they appear more often in training data.
The “Do Not Touch” section for components/ui/ prevents Claude Code from editing shadcn/ui files directly, which would break future updates via the shadcn CLI.
Example 4: Monorepo
This template covers a monorepo root CLAUDE.md with pointers to package-level files.
# platform-monorepo
Monorepo containing the API, web dashboard, and shared packages.
Uses pnpm workspaces.
## Structure
- apps/api: Node.js REST API (see apps/api/CLAUDE.md)
- apps/web: Next.js dashboard (see apps/web/CLAUDE.md)
- packages/shared: Shared TypeScript types and utilities
- packages/ui: Shared React component library
## Monorepo Conventions
- Package manager: pnpm (do not use npm or yarn)
- Run commands from the repo root using pnpm --filter
- Shared types go in packages/shared/src/types/, not duplicated in apps
- Never add a dependency to packages/shared without discussion
## Workspaces
- Install deps: pnpm install (from root)
- Run a script in one package: pnpm --filter @platform/api dev
- Run all dev servers: pnpm dev (runs all apps concurrently)
- Run all tests: pnpm test
## Do Not Touch
- pnpm-lock.yaml (managed by pnpm automatically)
- packages/ui/src/primitives/ (generated from design tokens)
## Cross-Package Changes
- Type changes in packages/shared affect all apps; check for downstream impacts
- UI component changes in packages/ui may affect both apps
- When making cross-package changes, run pnpm test from the root before committing
Why this structure works: The monorepo CLAUDE.md stays high-level and delegates to package-level CLAUDE.md files. Claude Code reads both when working in a specific package: the root CLAUDE.md for monorepo-wide rules, and the package CLAUDE.md for package-specific conventions. This avoids one enormous CLAUDE.md that tries to cover everything.
Example 5: Data Pipeline
This template covers a data engineering project using pandas/polars and Python.
# etl-pipeline
Daily ETL pipeline that ingests sales data from 3 sources,
transforms it, and loads it into the analytics warehouse.
## Stack
- Python 3.11
- Polars 0.20 for transformations (not pandas)
- DuckDB for local aggregation and testing
- Pydantic v2 for data validation schemas
- Great Expectations for data quality checks
- pytest for tests
## Conventions
- Use Polars, not pandas (consistent codebase, better performance)
- All schemas defined as Pydantic models in src/schemas/
- Validate input data before any transformation (use src/validation/)
- Log with structlog, not the logging module; use structured JSON output
- Each pipeline stage is a pure function: input DataFrame, output DataFrame
- Never mutate DataFrames in place; always return new ones
## Data Conventions
- Dates: always store as Python date objects, not strings
- Nulls: represent missing data as None/null, not 0 or empty string
- Column names: snake_case throughout
- Monetary amounts: store as integers (cents), not floats
## Testing
- Tests: tests/
- Run: pytest
- Use small sample DataFrames (10-100 rows) in unit tests, not production data
- Integration tests run against test copies of source data in tests/fixtures/
## Do Not Touch
- src/schemas/ (schema changes require a migration plan)
- Production data directories (never hardcode production paths)
## File Structure
- Extractors: src/extract/
- Transformers: src/transform/
- Loaders: src/load/
- Validation: src/validation/
- Schemas: src/schemas/
- Utilities: src/utils/
## Logging
- Log at the start and end of each stage with row counts
- Log any records that fail validation (do not silently drop them)
Why each section matters: The “Data Conventions” section is the most important part of a data pipeline CLAUDE.md. Monetary amounts stored as floats will introduce floating-point errors. Null representation inconsistency causes silent bugs. These are decisions that do not show up in code structure but matter enormously for data integrity.
Common CLAUDE.md Mistakes
Too long. A CLAUDE.md over 400 lines is usually full of generic best practices and copied documentation. Claude Code reads the whole file every session. A long file increases session startup time and dilutes the important instructions.
Too generic. “Follow RESTful conventions” tells Claude Code nothing it does not already know. “Return 201 on resource creation with a Location header pointing to the new resource” is specific and actionable.
Missing the “Do Not Touch” section. This is the most valuable section in any CLAUDE.md. Think about the files that, if accidentally modified, would cost you the most time to recover. List those files explicitly.
No testing section. Without a testing section, Claude Code will not know whether to write tests alongside new code, which test framework to use, or where test files should go.
Not maintained. A CLAUDE.md written once and never updated drifts from reality. When you change your testing framework, update CLAUDE.md. When you change your error response shape, update CLAUDE.md. Outdated instructions produce worse output than no instructions.
Build Your CLAUDE.md with Expert Guidance
Phos has helped 400+ teams set up Claude Code effectively, and CLAUDE.md quality is consistently the biggest factor in whether a team gets good output from day one or spends weeks correcting bad output. We are a CCA-F certified Claude partner.
Talk to the Phos team to get expert help building a CLAUDE.md that works for your specific stack and conventions.
FAQ
Can I have multiple CLAUDE.md files in different directories of the same project?
Yes. You can place a CLAUDE.md at any directory level. Claude Code reads the CLAUDE.md in the current working directory and any parent directories up to the repo root. In a monorepo, this means you can have a root-level CLAUDE.md for global rules and package-level CLAUDE.md files for package-specific conventions.
How do I know if my CLAUDE.md is working?
The clearest signal: Claude Code stops making the mistakes you documented. If you added a “use CommonJS” rule and Claude Code stops generating ESM syntax, the rule is working. If the same mistakes keep happening, the instruction is too vague or Claude Code is not reading that section. Make the instruction more specific.
Should different team members have different CLAUDE.md files?
The project CLAUDE.md should be shared and committed to the repo so all team members get consistent behavior. Individual preferences (like preferred response verbosity) should go in each person’s global CLAUDE.md (~/.claude/CLAUDE.md), which is not committed to the repo.
What is the maximum length for a CLAUDE.md?
There is no hard limit, but practical effectiveness drops off significantly after 300 to 400 lines. If your CLAUDE.md is growing large, audit it: remove generic instructions, move long documentation to actual docs files, and split monorepo-level files into package-level files. Shorter and more specific is always better.