Files
next.js/CLAUDE.md
T
Jimmy LaiandGitHub 3c47bd99af chore: add Claude Code configuration (#87943)
adding basic config with graphite/repo instructions

<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the PR.
- Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to understand the PR)
- When linking to a Slack thread, you might want to share details of the conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->
2026-01-05 13:32:27 +01:00

6.6 KiB

Next.js Development Guide

Git Workflow

Use Graphite for all git operations instead of raw git commands:

  • gt create <branch-name> -m "message" - Create a new branch with commit
  • gt modify -a --no-edit - Stage all and amend current branch's commit
  • gt checkout <branch> - Switch branches (use instead of git checkout)
  • gt sync - Sync and restack all branches
  • gt submit --no-edit - Push and create/update PRs (use --no-edit to avoid interactive prompts)
  • gt log short - View stack status

Note: gt submit runs in interactive mode by default and won't push in automated contexts. Always use gt submit --no-edit or gt submit -q when running from Claude.

Graphite Stack Safety Rules:

  • Graphite force-pushes everything - old commits only recoverable via reflog
  • Never have uncommitted changes when switching branches - they get lost during restack
  • Never use git stash with Graphite - causes conflicts when gt modify restacks
  • Never use git checkout HEAD -- <file> after editing - silently restores unfixed version
  • Always use gt checkout (not git checkout) to switch branches
  • gt modify --no-edit with unstaged/untracked files stages ALL changes
  • gt sync pulls FROM remote, doesn't push TO remote
  • gt modify restacks children locally but doesn't push them
  • Always verify with git status -sb after stack operations
  • When resuming from summarized conversation, never trust cached IDs - re-fetch from git/GitHub API

Safe multi-branch fix workflow:

gt checkout parent-branch
# make edits
gt modify -a --no-edit        # Stage all, amend, restack children
git show HEAD -- <files>      # VERIFY fix is in commit
gt submit --no-edit           # Push immediately

gt checkout child-branch      # Already restacked from gt modify
# make edits
gt modify -a --no-edit
git show HEAD -- <files>      # VERIFY
gt submit --no-edit

Build Commands

# Build the Next.js package (dev server only - faster)
pnpm --filter=next build:dev-server

# Build everything
pnpm build

# Run specific task
pnpm --filter=next taskfile <task>

Fast Local Development

For iterative development, use watch mode + fast test execution:

1. Start watch build in background:

# Runs taskr in watch mode - auto-rebuilds on file changes
# Use Bash(run_in_background=true) to keep working while it runs
pnpm --filter=next dev

2. Run tests fast (no isolation, no packing):

# NEXT_SKIP_ISOLATE=1 - skip packing Next.js for each test (much faster)
# testonly - runs with --runInBand (no worker isolation overhead)
NEXT_SKIP_ISOLATE=1 NEXT_TEST_MODE=dev pnpm testonly test/path/to/test.ts

3. When done, kill the background watch process.

Only use full pnpm --filter=next build for one-off builds (after branch switch, before CI push).

Always rebuild after switching branches:

gt checkout <branch>
pnpm build   # Required before running tests (Turborepo dedupes if unchanged)

Testing

# Run specific test file (development mode with Turbopack)
pnpm test-dev-turbo test/path/to/test.test.ts

# Run tests matching pattern
pnpm test-dev-turbo -t "pattern"

# Run development tests
pnpm test-dev-turbo test/development/

Test commands by mode:

  • pnpm test-dev-turbo - Development mode with Turbopack (default)
  • pnpm test-dev-webpack - Development mode with Webpack
  • pnpm test-start-turbo - Production build+start with Turbopack
  • pnpm test-start-webpack - Production build+start with Webpack

Other test commands:

  • pnpm test-unit - Run unit tests only (fast, no browser)
  • pnpm testonly <path> - Run tests without rebuilding (faster iteration)
  • pnpm new-test - Generate a new test file from template

Linting and Types

pnpm lint              # Full lint (types, prettier, eslint, ast-grep)
pnpm lint-fix          # Auto-fix lint issues
pnpm prettier-fix      # Fix formatting only
pnpm types             # TypeScript type checking

Investigating CI Test Failures

Use /ci-failures for automated analysis - analyzes failing jobs in parallel and groups by test file.

CI Analysis Tips:

  • Don't spawn too many parallel agents hitting GitHub API (causes rate limits)
  • Prioritize blocking jobs first: lint, types, then test jobs
  • Use gh api for logs (works on in-progress runs), not gh run view --log

Quick triage:

# List failed jobs for a PR
gh pr checks <pr-number> | grep fail

# Get failed job names
gh run view <run-id> --json jobs --jq '.jobs[] | select(.conclusion == "failure") | .name'

# Search job logs for errors (completed runs only - use gh api for in-progress)
gh run view <run-id> --job <job-id> --log 2>&1 | grep -E "FAIL|Error|error:" | head -30

Common failure patterns:

  • rust check / build → Run cargo fmt -- --check locally, fix with cargo fmt
  • lint / build → Run pnpm prettier --write <file> for prettier errors
  • Test failures → Run the specific test locally with pnpm test-dev-turbo <test-path>

Run tests in the right mode:

# Dev mode (Turbopack)
pnpm test-dev-turbo test/path/to/test.ts

# Prod mode
pnpm test-start-turbo test/path/to/test.ts

Key Directories

  • packages/next/src/ - Main Next.js source code
    • server/ - Server runtime (dev server, router, rendering)
    • client/ - Client-side code
    • build/ - Build tooling (webpack, turbopack configs)
    • cli/ - CLI entry points
  • packages/next/dist/ - Compiled output
  • turbopack/ - Turbopack bundler (Rust)
  • test/ - Test suites
    • development/ - Dev server tests
    • production/ - Production build tests
    • e2e/ - End-to-end tests

Development Tips

  • The dev server entry point is packages/next/src/cli/next-dev.ts
  • Router server: packages/next/src/server/lib/router-server.ts
  • Use DEBUG=next:* for debug logging
  • Use NEXT_TELEMETRY_DISABLED=1 when testing locally

Commit and PR Style

  • Do NOT add "Generated with Claude Code" or co-author footers to commits or PRs
  • Keep commit messages concise and descriptive
  • PR descriptions should focus on what changed and why

Development Anti-Patterns

Test Gotchas

  • Mode-specific tests need skipStart: true + manual next.start() in beforeAll after mode check
  • Don't rely on exact log messages - filter by content patterns, find sequences not positions

Rust/Cargo

  • cargo fmt uses ASCII order (uppercase before lowercase) - just run cargo fmt

Node.js Source Maps

  • findSourceMap() needs --enable-source-maps flag or returns undefined
  • Source map paths vary (webpack: ./src/, tsc: src/) - try multiple formats
  • process.cwd() in stack trace formatting produces different paths in tests vs production