Skip to content
Lesson 6 of 22

Mastering CLAUDE.md

16 min read

What is CLAUDE.md and Why It Matters

Every time you start a new conversation with Claude Code, it reads a special file in your project called CLAUDE.md. This file contains persistent instructions that shape every response the AI gives you. Think of it as the project's institutional memory — the accumulated wisdom about how your project works, what conventions to follow, and what pitfalls to avoid.

Without CLAUDE.md, every conversation starts from zero. You have to re-explain your tech stack, remind the AI about your coding conventions, and correct the same mistakes over and over. With a well-crafted CLAUDE.md, the AI already knows all of this. It's the difference between working with a new contractor every day and working with someone who's been on your team for months.

Here's a helpful analogy: imagine you're onboarding a new developer. You wouldn't just point them at the codebase and say "figure it out." You'd give them documentation about the project's architecture, coding standards, deployment process, and the decisions that shaped the codebase. CLAUDE.md is that onboarding document — except the new developer reads it at the start of every single session.

The file lives at the root of your project directory and is written in Markdown. Claude Code automatically detects and reads it before processing any of your prompts. There is no special syntax or configuration required — just create the file, write your instructions, and they take effect immediately.

Anatomy of a Great CLAUDE.md

A great CLAUDE.md is organized into clear sections, each serving a specific purpose. Let's break down the essential sections and what belongs in each one.

Project Overview

Start with a brief description of what the project is and who it's for. This sets the mental model for everything that follows.

# Project Overview

SaaSKit is a subscription management platform for small businesses.
Users can create accounts, manage their subscription plans, track
usage, and handle billing. The target audience is non-technical
small business owners, so the UI prioritizes simplicity over power-user features.

This might seem obvious, but it prevents the AI from making wrong assumptions. Knowing the audience is "non-technical small business owners" means the AI will favor simple, intuitive designs over feature-dense dashboards.

Tech Stack

List every major technology in your project. Be specific about versions when it matters.

# Tech Stack

- **Framework:** Next.js 14 with App Router (NOT Pages Router)
- **Language:** TypeScript (strict mode)
- **Styling:** Tailwind CSS v3 with custom design tokens in tailwind.config.ts
- **Database:** PostgreSQL via Supabase
- **ORM:** Drizzle ORM (NOT Prisma)
- **Auth:** NextAuth.js v5 with email + Google providers
- **Payments:** Stripe (Checkout + Customer Portal)
- **Email:** Resend with React Email templates
- **Deployment:** Vercel
- **Testing:** Vitest + Testing Library

Notice the "NOT Pages Router" and "NOT Prisma" notes. These are critical. AI models have training data from many eras and many projects. Without explicit direction, Claude might generate Pages Router code or Prisma syntax because those are common in its training data. The explicit negations prevent this.

Architecture Decisions

Document your project's structure and the reasoning behind key decisions.

# Architecture

## Directory Structure
- `app/` — Next.js App Router pages and layouts
- `app/api/` — API route handlers
- `app/(auth)/` — Authentication pages (login, register, forgot-password)
- `app/(dashboard)/` — Protected dashboard pages
- `components/` — Reusable React components
- `components/ui/` — Base UI components (Button, Input, Modal, etc.)
- `components/features/` — Feature-specific components
- `lib/` — Utility functions, database queries, server-side logic
- `lib/db/` — Drizzle schema and database utilities
- `types/` — Shared TypeScript types and interfaces

## Key Patterns
- Server Components by default. Use "use client" only when needed for
  interactivity (event handlers, hooks, browser APIs).
- Data fetching happens in Server Components, never in client components.
- All forms use React Server Actions defined in `app/actions/`.
- Error boundaries at the route segment level using error.tsx files.
- Loading states using loading.tsx with skeleton components.

This section is one of the highest-value parts of CLAUDE.md. When the AI knows your directory structure and patterns, it puts new files in the right place and follows established conventions automatically.

Coding Standards

Define how code should be written in your project.

# Coding Standards

- Use `async/await` for all asynchronous code. Never use raw `.then()` chains.
- Destructure imports: `import { Button } from "@/components/ui/Button"`
- Use named exports, not default exports (except for Next.js pages).
- All components must have TypeScript props interfaces defined above the component.
- Use `cn()` utility (from lib/utils.ts) for conditional class names, not string concatenation.
- Error handling: wrap database calls in try/catch, return typed error objects, never throw in server actions.
- Prefer early returns over nested if/else blocks.
- Maximum file length: 200 lines. If a file exceeds this, extract components or utilities.

Boundaries and Do-NOT Rules

This section prevents the AI from making changes that would break things or conflict with your preferences.

# Boundaries

- NEVER modify the database schema files without explicit approval.
- NEVER install new dependencies without asking first.
- NEVER use `any` type in TypeScript. Use `unknown` and type narrow instead.
- NEVER use inline styles. Always use Tailwind classes.
- NEVER create new API routes when a Server Action would work.
- Do NOT use the `pages/` directory — this project uses App Router exclusively.
- Do NOT use CSS modules, styled-components, or any CSS-in-JS library.
- Do NOT use relative imports for cross-directory references. Always use the `@/` path alias.

These rules are guardrails. They prevent the AI from straying into territory that would create technical debt or break your project's conventions.

Workflow Preferences

Tell the AI how you like to work.

# Workflow

- Use conventional commits: feat:, fix:, refactor:, docs:, test:, chore:
- Run tests after every change: `npm run test`
- Before creating a PR, run `npm run lint && npm run typecheck && npm run test`
- Commit messages should be concise and in imperative mood: "add user dashboard" not "added user dashboard"
- Create small, focused commits — one feature or fix per commit
- Always review diffs before committing

Real-World Templates

Let's look at complete CLAUDE.md files for different project types. These are starting points you can adapt for your own projects.

Template: Next.js SaaS Application

# Project: CloudTrack — SaaS Analytics Platform

## Overview
CloudTrack is a web analytics platform for small e-commerce stores.
Users sign up, install a tracking script on their site, and view
visitor analytics in a dashboard. Freemium model with paid tiers.

## Tech Stack
- Next.js 14 (App Router, TypeScript strict)
- Tailwind CSS + shadcn/ui components
- PostgreSQL on Supabase (Drizzle ORM)
- NextAuth.js v5 (Google + email magic links)
- Stripe for billing (Checkout Sessions + Webhooks)
- Vercel for deployment
- Vitest + Playwright for testing

## Architecture
- app/(marketing)/ — Public pages (landing, pricing, docs)
- app/(dashboard)/ — Protected analytics dashboard
- app/api/track/ — Analytics event ingestion endpoint
- app/api/webhooks/ — Stripe and external webhooks
- components/charts/ — Chart components using Recharts
- lib/analytics/ — Query builders for analytics data
- lib/db/schema.ts — Single source of truth for database schema

## Standards
- Server Components by default, "use client" only for interactive elements
- All data fetching in server components using functions from lib/
- Forms use Server Actions in app/actions/
- Use cn() for conditional Tailwind classes
- Named exports everywhere except page.tsx files
- No any types — use unknown + type narrowing

## Do NOT
- Never modify lib/db/schema.ts without asking
- Never install new packages without approval
- Never use CSS modules or styled-components
- Never expose server-only code to client components
- Never store sensitive data in localStorage

## Workflow
- Conventional commits (feat:, fix:, etc.)
- Run `npm run check` before every commit (lint + typecheck + test)

Template: Landing Page / Marketing Site

# Project: LaunchPage — Product Landing Site

## Overview
A single-page marketing site for a mobile app launch. Goal: collect
email signups for the waitlist. Target: non-technical users.
Must be fast, beautiful, and work perfectly on mobile.

## Tech Stack
- Next.js 14 (App Router, TypeScript)
- Tailwind CSS with custom theme in tailwind.config.ts
- Framer Motion for animations
- Resend for waitlist email confirmation
- Vercel deployment
- No database — waitlist emails stored via Resend audience

## Architecture
- app/page.tsx — Single landing page with all sections
- components/sections/ — Hero, Features, Testimonials, Pricing, CTA, Footer
- components/ui/ — Button, Input, Badge, Card
- app/actions/waitlist.ts — Server Action for email signup
- public/ — Images, app screenshots, social previews

## Design
- Color palette: defined in tailwind.config.ts (do not deviate)
- Font: Inter for body, Cal Sans for headings (loaded via next/font)
- Animations: subtle, fast (200-300ms), triggered on scroll using
  Framer Motion InView
- Mobile-first: design for 375px width first, then scale up

## Do NOT
- No JavaScript-heavy features that hurt Lighthouse scores
- No cookie banners (we don't use cookies)
- No external scripts except the analytics pixel in layout.tsx
- Don't add new pages without asking — this is intentionally a single-page site

## Performance
- Target: Lighthouse 95+ on all metrics
- All images use next/image with proper width/height
- Lazy load everything below the fold

Template: REST API Service

# Project: OrderAPI — Order Management REST API

## Overview
A REST API that handles order processing for an e-commerce platform.
Consumed by a separate React frontend and a mobile app.
Must be reliable, well-documented, and handle high traffic.

## Tech Stack
- Node.js with Express.js (TypeScript strict)
- PostgreSQL (Drizzle ORM)
- Redis for caching and rate limiting
- Zod for request validation
- JWT authentication
- Docker for local development
- Jest for testing

## Architecture
- src/routes/ — Route definitions grouped by resource
- src/controllers/ — Request handlers (thin — call services)
- src/services/ — Business logic (where the real work happens)
- src/middleware/ — Auth, validation, error handling, rate limiting
- src/db/ — Schema, migrations, query utilities
- src/types/ — Shared TypeScript interfaces

## Standards
- Every endpoint must have Zod validation on request body/params/query
- Controllers are thin: validate input, call service, return response
- Services contain all business logic and database calls
- Return consistent error format: { error: string, code: string, status: number }
- All database queries go through the service layer, never in controllers
- Use transactions for multi-step operations

## Do NOT
- Never return raw database errors to the client
- Never skip input validation
- Never use raw SQL — always use Drizzle query builder
- Never store passwords in plain text (use bcrypt)

Template: CLI Tool

# Project: Deployer — CLI Deployment Tool

## Overview
A command-line tool that simplifies deploying Node.js apps to various
cloud providers. Users run `deployer init` to configure, then
`deployer deploy` to ship.

## Tech Stack
- Node.js (TypeScript strict)
- Commander.js for CLI argument parsing
- Inquirer.js for interactive prompts
- chalk for colored terminal output
- ora for spinners and loading indicators
- conf for persistent configuration

## Architecture
- src/commands/ — One file per CLI command (init, deploy, status, logs)
- src/providers/ — Cloud provider adapters (vercel, aws, railway)
- src/utils/ — Shared utilities (logging, config, API clients)
- src/types/ — TypeScript interfaces

## Standards
- Every command must show a help message with --help
- Use spinners for any operation longer than 1 second
- Color coding: green for success, red for errors, yellow for warnings
- All errors must show a clear message AND a suggested fix
- Config stored in ~/.deployer/config.json

## Do NOT
- Never store credentials in the config file — use env vars or OS keychain
- Never run destructive operations without confirmation prompt
- Never swallow errors silently — always log them

How CLAUDE.md Evolves

Your CLAUDE.md should not be a static document. It grows and improves as your project evolves. Here's the lifecycle:

Start minimal. When you begin a project, your CLAUDE.md might just have the project overview and tech stack. That's enough to get started.

Add rules when you notice repeated corrections. If you find yourself telling the AI "don't use default exports" for the third time, that's a rule that belongs in CLAUDE.md. Every repeated correction is a signal that a rule is missing.

Remove rules that are too restrictive. If a rule is forcing the AI to write awkward code or you keep overriding it, the rule might be wrong. Remove it or soften it.

Version it with git. Your CLAUDE.md is code. Track it in version control so you can see how it changes over time and roll back if a change causes problems.

Review it periodically. Once a month, read through your CLAUDE.md and ask: Is this still accurate? Are there new patterns we've established that aren't documented? Are any rules outdated?

The best CLAUDE.md files are living documents that reflect the current state of the project and the team's preferences. They grow organically from real experience rather than being written as an aspirational document on day one.

Nested CLAUDE.md Files

Claude Code supports multiple CLAUDE.md files at different levels of your project. The root-level file applies to everything, while directory-level files add context for specific areas.

The root CLAUDE.md is the default for the entire project:

project/
  CLAUDE.md           <-- Project-wide rules
  src/
    components/
      CLAUDE.md       <-- Component-specific rules
    api/
      CLAUDE.md       <-- API-specific rules

For example, your root CLAUDE.md might say "use Tailwind CSS for all styling," while a src/api/CLAUDE.md might add:

# API Directory Rules

- Every route handler must validate the request body with Zod.
- Return standard error responses using the errorResponse() helper from lib/errors.ts.
- Log all errors using the logger from lib/logger.ts.
- Rate limiting is applied globally in middleware — don't add per-route rate limiting.

And a src/components/CLAUDE.md might add:

# Component Rules

- All components in ui/ are generic, reusable building blocks. They should
  not import from features/ or contain business logic.
- All components in features/ are specific to a feature and can import from ui/.
- Every component must accept a className prop for style overrides.
- Use forwardRef for all components that render native HTML elements.

This layered approach lets you be specific without cluttering the root file. The AI reads all applicable CLAUDE.md files from the root down to the current working directory, applying them in order.

Common Mistakes

Even experienced developers make mistakes with their CLAUDE.md. Here are the most common ones and how to avoid them.

Too Generic

# Bad Example
Write clean code. Follow best practices. Use good naming conventions.

This says nothing useful. What does "clean" mean in your project? What are the best practices you follow? What naming convention do you use — camelCase, PascalCase, kebab-case? If a rule doesn't change the AI's behavior in a concrete way, it doesn't belong in CLAUDE.md.

Too Restrictive

# Bad Example
- NEVER use ternary operators
- NEVER use arrow functions for component definitions
- NEVER use spread operators
- ALWAYS write explicit return types for every function
- ALWAYS add JSDoc comments to every function

If the AI can't use common JavaScript patterns, it will write verbose, awkward code. Restrictions should prevent real problems, not enforce stylistic preferences that don't impact quality.

Outdated Information

# Bad Example (project migrated from Pages Router months ago)
Use the Pages Router with getServerSideProps for all data fetching.

An outdated CLAUDE.md is worse than no CLAUDE.md at all because it actively steers the AI in the wrong direction. When you make architectural changes, update CLAUDE.md immediately.

Too Long

A CLAUDE.md that's 2,000 lines long dilutes the important rules with noise. AI models have limited attention spans — the more text they need to process, the less likely they are to follow every instruction. Aim for 100-300 lines of high-signal content. If you need more, use nested CLAUDE.md files to distribute the information.

The Multiplier Effect

Here is why CLAUDE.md deserves your attention: it has compound returns.

Consider a project where you interact with Claude Code 20 times per day. Without CLAUDE.md, maybe 5 of those interactions require corrections about coding conventions, tech stack choices, or project structure. Each correction takes 2-3 minutes, including the follow-up prompt and waiting for the revised output. That's 10-15 minutes per day spent on corrections that CLAUDE.md would prevent.

Over a month of working days, that's 3-5 hours of wasted time. Over the lifetime of a project, it's days or weeks.

But the benefit goes beyond time savings. With a well-configured CLAUDE.md:

  • Consistency improves. Every piece of generated code follows the same patterns, making the codebase easier to understand and maintain.
  • Onboarding speeds up. If another person (or your future self) starts working on the project, the CLAUDE.md brings them up to speed immediately.
  • Quality increases. When AI knows about your error handling patterns, security requirements, and testing expectations, it includes them by default instead of only when reminded.
  • Creativity expands. When you're not spending mental energy correcting conventions, you can focus on the creative decisions — the features, the UX, the product.

Every minute invested in CLAUDE.md saves hours of repeated corrections over the project's lifetime. It is the highest-leverage activity in vibe coding.

What's Next

With strong prompt skills and a well-configured CLAUDE.md, you're producing code faster than ever. But speed creates a new risk: what happens when something goes wrong and you want to undo it?

In the next lesson, we'll cover Git workflows for vibe coders — the safety net that lets you experiment fearlessly, recover from mistakes instantly, and manage your project like a professional developer. Git is the tool that makes AI-assisted development safe.