CLAUDE CODE
How I Write CLAUDE.md Files That Actually Work
A practical guide to writing CLAUDE.md files that Claude Code actually follows, with real production examples from my Next.js portfolio site and the mistakes I learned the hard way.
A CLAUDE.md file is the single most impactful thing you can add to any project using Claude Code. It tells Claude how to build, test, and work with your codebase - and when written well, it eliminates the repetitive corrections that slow down AI-assisted development. After months of iteration on my own production site, I have a system that works.
- 1.Keep CLAUDE.md under 60-80 lines. Use @imports for anything longer.
- 2.Lead with build commands and hard constraints - Claude reads these first and retains them best.
- 3.Use positive instructions (“use X”) instead of negations (“don't use Y”) - Claude follows positive rules more reliably.
- 4.Add rules reactively - only when Claude makes the same mistake twice. Never front-load speculative rules.
- What Is a CLAUDE.md File?
- The Anatomy of an Effective CLAUDE.md
- My Production CLAUDE.md: A Line-by-Line Breakdown
- CLAUDE.md for Next.js Projects: Stack-Specific Rules
- 7 CLAUDE.md Mistakes That Waste Your Tokens
- CLAUDE.md vs Hooks vs Custom Commands: When to Use What
- How I Keep My CLAUDE.md Fresh
- Frequently Asked Questions
What Is a CLAUDE.md File?
CLAUDE.md is a Markdown file that provides project-specific instructions to Claude Code. When you start a session, Claude reads every CLAUDE.md file it finds - from your global config to your project root to nested subdirectories - and uses those instructions as context for the entire conversation. Think of it as a README, but written specifically for your AI coding partner.
According to JetBrains' 2026 developer survey, 40.8% of developers using AI agents use Claude Code - the most popular AI coding agent. Yet many users never create a CLAUDE.md file, leaving significant productivity gains untapped.
The Hierarchical Loading System
Claude Code loads CLAUDE.md files from multiple locations, with more specific files taking precedence over general ones:
~/.claude/CLAUDE.md # Global - your personal preferences across all projects
/project-root/CLAUDE.md # Project - shared team standards (commit to repo)
/project-root/.claude/CLAUDE.md # Project - alternative location
/project-root/src/CLAUDE.md # Subdirectory - scoped rules for a specific areaI use the global file for personal preferences (editor style, commit message format) and the project-level file for architecture rules specific to each codebase.
The Anatomy of an Effective CLAUDE.md
An effective CLAUDE.md has five essential sections, ordered by importance. Claude retains content near the top and bottom of long files better than the middle - a well-documented primacy/recency effect in LLMs. Place your most critical rules first.
1. Project Overview (1-2 sentences)
What the project is and what stack it uses. Claude needs this context to make informed decisions about every change it suggests.
2. Build / Test / Lint Commands
The exact commands to build and test the project. Claude runs these dozens of times per session - get them right first.
3. Architecture Rules and Constraints
Hard constraints like “static export only” or “never modify files in src/components/ui/”. These prevent impossible or destructive changes.
4. File and Folder Conventions
Where things go, how files are named, directory structure. Claude uses this to place new files correctly.
5. Common Patterns and Examples
Code templates Claude should follow when creating new pages, components, or features. Show the preferred way, not just the rules.
Research from HumanLayer suggests keeping CLAUDE.md under 60-80 lines for optimal instruction adherence. Use the @import syntax to reference external docs and keep the file lean:
# Project Overview
Portfolio site - Next.js 16 static export + shadcn/ui.
## Commands
See @package.json for all scripts. Key ones:
- `npm run dev` - dev server on localhost:3000
- `npm run build` - static export to ./out
- `npm run lint` - ESLint check
## Architecture
See @docs/architecture.md for full system design.
## Git Workflow
See @docs/git-instructions.md for branch strategy.My Production CLAUDE.md: A Line-by-Line Breakdown
This is the actual CLAUDE.md from avinashsangle.com, a Next.js 16 static site with shadcn/ui deployed to GitHub Pages. Every rule exists because Claude made a specific mistake without it.
The Project Overview and Commands
# CLAUDE.md
This file provides guidance to Claude Code when working with this repository.
## Project Overview
Personal portfolio website - Next.js 16 static site with shadcn/ui,
deployed to GitHub Pages via GitHub Actions.
## Tech Stack
- Framework: Next.js 16 (App Router) with static export
- Styling: Tailwind CSS 4 with shadcn/ui components
- Icons: Lucide React (replaced emojis throughout)
- Deployment: GitHub Pages via GitHub Actions
## Development Commands
```bash
npm run dev # Dev server on localhost:3000
npm run build # Static export to ./out folder
npm run lint # ESLint
```The tech stack section prevents Claude from suggesting incompatible patterns - like server-side rendering or API routes that would break the GitHub Pages deployment.
The Hard Constraints That Prevent Real Mistakes
## Critical Architecture Rules
### 1. Static Export - NO Server Features
**CRITICAL:** All pages must be statically exportable.
No server-side rendering, API routes, or getServerSideProps.
next.config.ts must stay as:
output: 'export'
trailingSlash: true
images: { unoptimized: true }
### 2. shadcn/ui Components - DO NOT MODIFY
**CRITICAL:** NEVER modify files in src/components/ui/
These are installed via CLI and must stay pristine.
Style changes go in:
- src/app/globals.css (global styles)
- src/app/**/page.tsx (Tailwind classes on elements)
- src/components/navbar.tsx (layout components)
### 3. Icons - Lucide Only, No Emojis
Use CategoryIcon from @/components/icons/category-icon
NEVER add emoji characters to any fileWhy each of these rules exists:
- Static export rule: Claude suggested an API route. Build broke on GitHub Pages deploy.
- shadcn/ui rule: Claude edited Button.tsx directly. Broke on next shadcn/ui update.
- No emojis rule: Claude added emoji to a heading. Looked unprofessional, took 20 minutes to find.
Showing Patterns - More Effective Than Rules
The most effective section in my CLAUDE.md is the page structure template. Rather than listing abstract rules, I show Claude exactly what a well-formed page looks like. According to Anthropic's 2026 Agentic Coding Trends Report, AI is projected to generate 60% of code by end of 2026. Templates ensure that generated code matches your established patterns from day one.
## Common Patterns
### New Blog Article Checklist
1. Create: src/app/blog/[slug]/page.tsx
2. Add metadata export (title 55-65 chars, description 130-160 chars)
3. Add TechArticle + BreadcrumbList + FAQPage JSON-LD schemas
4. Update src/app/blog/page.tsx with new article card
5. Update src/app/sitemap.ts with new slug
### Required JSON-LD Author Object (all articles)
{
"@type": "Person",
"name": "Avinash Sangle",
"url": "https://avinashsangle.com",
"sameAs": ["https://www.linkedin.com/in/avinashsangle", ...]
}CLAUDE.md for Next.js Projects: Stack-Specific Rules
Next.js App Router introduces conventions that differ significantly from traditional React. Generic Claude Code rules are not enough - you need stack-aware constraints. There is currently only one public CLAUDE.md example for Next.js + shadcn/ui. Here is what I have learned works.
## Next.js App Router Conventions
### Routing Structure
src/app/page.tsx → /
src/app/blog/page.tsx → /blog
src/app/blog/[slug]/page.tsx → /blog/[slug]
### SEO Requirements (STRICT character limits)
All pages must export metadata with:
- title: 55-65 characters (Bing truncates beyond 70)
- description: 130-160 characters (Bing prefers 150-160)
- Full OpenGraph + Twitter Card tags
- JSON-LD schemas appropriate to page type
### Static Export Hard Rules
No getServerSideProps or getInitialProps
No API routes (src/app/api/ does not exist)
No next/headers or next/cookies imports
No Image optimization (unoptimized: true is set)
All dynamic routes need generateStaticParams
### Import Style
Always use path aliases:
import { Button } from "@/components/ui/button" ✓
import { Button } from "../../components/ui/button" ✗The SEO character limits were added after Claude generated a 91-character title that Bing truncated in search results. Being specific about the numbers (“55-65 chars”) works far better than vague instructions like “keep titles short.”
Next.js maintains its own official AI Agents guide that recommends CLAUDE.md for configuring AI coding tools - recognizing that framework-specific rules cannot be inferred generically.
7 CLAUDE.md Mistakes That Waste Your Tokens
After iterating through dozens of CLAUDE.md versions and reading hundreds shared on r/ClaudeAI, these are the patterns that consistently cause problems. Files over 200 lines can consume 30-40K tokens at session start - real cost when paying per token on the API plan.
Mistake 1Using Negation Instead of Positive Instructions
Do NOT use semicolons.
Do NOT add console.log statements.
Do NOT import from relative paths.Style: no-semicolon (Prettier enforces this).
Logging: use logger from "@/lib/logger".
Imports: use path aliases (@/components/...).LLMs process positive instructions more reliably than negations. Give Claude a pattern to follow, not just things to avoid.
Mistake 2Documenting What Claude Already Knows
- Use async/await instead of callbacks
- Use const for immutable variables
- Add error handling to async functions
- Use TypeScript for type safety- Validation: use Zod (not io-ts or yup)
- Error boundaries: src/components/error-boundary.tsx
- API calls: always via src/lib/api-client.ts
- Dates: use date-fns (not moment.js)Only document project-specific decisions Claude cannot infer from the code itself.
Mistake 3The Documentation Dump
Pasting entire READMEs, API docs, or style guides inline. Use @imports instead:
# Instead of pasting 300 lines of API documentation:
See @docs/api-reference.md for all endpoint specifications.
See @README.md for project setup and background.Mistake 4Conflicting Rules
I once had “use functional components only” in one section and a class component in my code template. Claude alternated between both. Audit your CLAUDE.md for contradictions - they cause inconsistent, unpredictable behavior.
Mistake 5No Emphasis on Critical Rules
Not all rules deserve equal weight. Mark the ones that must never be violated:
**CRITICAL:** NEVER modify files in src/components/ui/
**Important:** All pages must be statically exportable.
**Note:** Prefer named exports for components.Mistake 6Never Pruning Stale Rules
Rules accumulate but rarely get removed. I deleted a rule about a deprecated API endpoint that had been gone for 3 months - consuming tokens for a constraint that no longer applied. Use git blame CLAUDE.md quarterly to identify rules past their useful life.
Mistake 7Treating /init Output as Final
The /init command is a solid starting point, but its output is often verbose with generic rules Claude already knows. Always review the output, delete the obvious entries, and add the project-specific constraints that matter.
CLAUDE.md vs Hooks vs Custom Commands: When to Use What
CLAUDE.md is not the only tool for configuring Claude Code's behavior. One of the most common mistakes is putting everything into CLAUDE.md when other mechanisms are more appropriate. Here is the decision framework I use.
| Mechanism | Best For | Enforcement | Example |
|---|---|---|---|
| CLAUDE.md | Preferences, conventions, architecture context | Soft | “Use Lucide icons, not emojis” |
| Hooks | Hard requirements, automated enforcement | Hard | Run ESLint after every file write |
| Custom Commands | Repeatable multi-step workflows | On invoke | /write-blogpost, /deploy, /review |
| Skills | Domain knowledge injection | Contextual | Testing patterns, design system rules |
My rule of thumb
If you find yourself writing “CRITICAL” or “NEVER” in CLAUDE.md, that rule probably belongs in a hook instead. Hooks enforce requirements deterministically - CLAUDE.md rules are guidelines Claude follows most of the time, not guarantees. I use hooks for linting and security checks, CLAUDE.md for architecture guidance and patterns.
How I Keep My CLAUDE.md Fresh
CLAUDE.md files rot. Rules that were essential 3 months ago may now be irrelevant, and gaps accumulate as the project evolves. Research shows that AI-cited content is 25.7% fresher on average than traditional organic results - the same freshness principle applies to the instructions your AI reads.
Add Rules Reactively
Only add a rule when Claude makes the same mistake twice. If it happens once, it may be a fluke. Twice means it is a pattern. This prevents the speculative rule accumulation that bloats CLAUDE.md with constraints you might need someday.
Quarterly Audit with Git Blame
Run git blame CLAUDE.md to see when each rule was added. If a rule is over 3 months old, verify the underlying constraint still exists. In my last audit I removed 8 stale rules - a significant token saving per session.
Let Claude Suggest Updates
At the end of a productive session, ask Claude: “Based on the mistakes I corrected today, what rules should I add to CLAUDE.md?” This creates a feedback loop where the file improves organically from real usage patterns.
Frequently Asked Questions
What to Read Next
CLAUDE.md sets the foundation. Next, explore hooks for automated enforcement, or see how I build MCP servers using Claude Code directly.