Skip to content
SaaS4Builders
Claude Code

CLAUDE.md Configuration

The three-tier CLAUDE.md file structure, progressive disclosure model, and how to customize AI agent context for your project.

CLAUDE.md files are the primary configuration mechanism for Claude Code. They provide always-on context that the agent loads automatically when it enters a directory. SaaS4Builders ships three CLAUDE.md files at strategic locations, each progressively adding domain-specific context.


The Three Configuration Files

FileLinesScopeLoaded When
CLAUDE.md~150Project-wideAlways (project root)
backend/CLAUDE.md~540Laravel backendWorking in backend/
frontend/CLAUDE.md~320Nuxt frontendWorking in frontend/

When Claude Code opens the project, it loads the root file. When you cd backend, it loads both root AND backend. When you cd frontend, it loads both root AND frontend. This layering means the agent always has the right level of context for the current work.


Root CLAUDE.md — The Project Map

The root file is the entry point for all AI-assisted work. At ~150 lines, it gives an agent enough context to navigate the full project without overwhelming its context window.

What It Contains

Project identity — Stack declaration (Laravel 13 + Nuxt 4), billing provider (Stripe), tenancy model (single-DB), supported locales (EN/FR/ES/IT).

Project structure — The directory layout an agent needs to find any file:

backend/    → Laravel API (has its own CLAUDE.md)
frontend/   → Nuxt 4 (has its own CLAUDE.md)
.claude/    → Skills, decisions, settings
docs/       → API contracts, milestones, specs
ai-context/ → Project brief, glossary, architecture

Docker commands — The full set of make commands for both stacks, grouped by concern (setup, backend, frontend, quality). Every command is copy-pasteable.

Domain entities — A table defining the nine core entities the agent will encounter:

CLAUDE.md
| Entity | Description |
|--------|-------------|
| **Tenant** | Customer org — all resources scoped by `tenant_id` (UUID) |
| **User** | Individual account, single tenant (int ID, nullable `tenant_id`) |
| **Product** | Logical offering (global catalog) |
| **Plan** | Pricing config: flat-rate / seat-based / usage-based |
| **Feature** | Functional capability gated by entitlements |
| **Entitlement** | Plan ↔ Feature link with limits (boolean or quota) |
| **Subscription** | Tenant ↔ Plan binding. Lifecycle: trialing → active → past_due → canceled |
| **Invoice** | Internal invoice (PDF). Immutable after paid. |
| **Meter/UsageEvent** | Usage tracking counters and events |

Critical conventions — The non-negotiable rules that apply everywhere:

  • API rules: snake_case JSON keys, ISO-8601 dates, amount_cents + currency for money, versioned under /api/v1/
  • Multi-tenancy: single DB with tenant_id scoping, BelongsToTenant trait, test isolation required
  • Git: conventional commits (feat(scope): message), branch prefixes (feature/, fix/, etc.)
  • Quality gates: PHPStan level 9, TypeScript strict, ESLint, coverage ≥80% on critical paths

Explicit guardrails — A "Do NOT" list that prevents the most dangerous mistakes:

  • Never bypass tenant isolation
  • Never hardcode secrets or credentials
  • Never skip tests for critical features (auth, billing, tenancy)
  • Never implement undocumented API endpoints

Skill references — A list of available /skill-name commands, so the agent knows what on-demand context is available.

The root file is intentionally concise. It provides just enough context for any task. Deep domain knowledge lives in skills, loaded on demand via /skill-name. This progressive disclosure model keeps the base context lean while providing unlimited depth when needed.

Backend CLAUDE.md — Laravel Conventions

At ~540 lines, the backend configuration file is the most comprehensive. It is auto-generated by Laravel Boost and provides everything an AI agent needs to write correct Laravel code in this project.

Docker Environment

Container names and command prefixes ensure the agent runs commands in the right place:

# All backend commands run inside the PHP container
docker compose exec php php artisan test --compact
docker compose exec php vendor/bin/pint --dirty
docker compose exec php vendor/bin/phpstan analyse --memory-limit=1G

PHP and Laravel Rules

Foundation conventions that prevent common mistakes:

  • PHP 8.4 with constructor property promotion and explicit return types
  • Eloquent over raw queries, eager loading to prevent N+1
  • Form Request classes for validation with custom messages
  • config() helper for environment variables (never env() directly)
  • Named routes with the route() function

Application Architecture

The core of the backend configuration — the modular domain-driven architecture:

app/
├── Application/<Domain>/        # Use cases (Actions, Queries, DTOs)
│   ├── Actions/                 # Write operations (mutations)
│   ├── Queries/                 # Read operations
│   └── DTO/                     # Input Data Transfer Objects
├── Domain/<Domain>/             # Core domain logic
│   ├── Contracts/               # Interfaces for external services
│   ├── DTO/                     # Domain Transfer DTOs (provider-agnostic)
│   └── Models/                  # Eloquent models (if domain-specific)
├── Infrastructure/<Domain>/     # External implementations
│   ├── Providers/<Provider>/    # Provider-specific implementations
│   └── Mappers/                 # External → Domain DTO mappers
└── Http/
    ├── Controllers/Api/V1/      # Thin controllers (delegation only)
    ├── Requests/Api/V1/         # Form Requests with toDto()
    └── Resources/Api/V1/        # API Resources (snake_case output)

The request flow is explicit:

Request → FormRequest::toDto() → Action/Query → Resource → Response

Where Code Goes

A decision table tells the agent exactly where to put new code:

I want to...I create in...
Create/update/delete an entityApplication/<Domain>/Actions/
List/filter/paginateApplication/<Domain>/Queries/
Define input data for a use caseApplication/<Domain>/DTO/*Data.php
Call an external serviceDomain/*/Contracts/ + Infrastructure/*/Providers/
Validate HTTP inputHttp/Requests/Api/V1/<Context>/
Format API outputHttp/Resources/Api/V1/<Context>/

Mandatory Rules

Six rules that the agent must never violate:

  1. Thin Controllers — Controllers delegate only. No business logic, no query building.
  2. Request → toDto() — Every FormRequest exposes toDto() mapping HTTP input to an Application DTO.
  3. Actions = Mutations — Wrap in DB::transaction(). Return Eloquent Model.
  4. Queries = Read-only — No side effects. May use Eloquent or Spatie QueryBuilder.
  5. Domain Contracts — Actions depend on interfaces, never on providers directly.
  6. Mappers — Normalize external responses to Domain Transfer DTOs.

Naming Conventions

A detailed table specifying naming patterns for every file type:

TypeLocationNamingNotes
ActionApplication/<Domain>/Actions/CreateX.phpNo suffix
QueryApplication/<Domain>/Queries/ListX.phpNo suffix
Input DTOApplication/<Domain>/DTO/CreateXData.php*Data or *Filters
Transfer DTODomain/<Domain>/DTO/ExternalX.phpProvider-agnostic
ContractDomain/<Domain>/Contracts/XGateway.phpInterface only
ProviderInfrastructure/<Domain>/Providers/X/StripeXGateway.phpImplements Contract
MapperInfrastructure/<Domain>/Mappers/StripeXMapper.phpExternal → Domain DTO
RequestHttp/Requests/Api/V1/<Context>/CreateXRequest.phpMust have toDto()
ResourceHttp/Resources/Api/V1/<Context>/XResource.phpsnake_case keys

Code Style Rules

  • All classes are final unless inheritance is explicitly needed
  • DTOs use readonly class
  • Resources output snake_case keys (enforced by API contracts)
  • Money fields: amount_cents (int) + currency (string) — never floats
  • Dates: ->toIso8601String() format

Additional Sections

The backend configuration also covers:

  • Test enforcement — Every change must be tested; run the minimum tests needed
  • Internationalization — Four locales (en, fr, es, it), file-per-domain translations
  • PR review checklist — Architecture, API contract, and quality checks
The backend CLAUDE.md is comprehensive because it handles a complex domain. Do not strip it down — the verbosity is intentional. Each section prevents a specific class of AI mistakes.

Frontend CLAUDE.md — Nuxt Conventions

At ~320 lines, the frontend configuration covers the vertical slice architecture and Nuxt-specific patterns.

Vertical Slice Architecture

The frontend organizes code into three feature layers:

features/
├── foundation/    # Layer 0 — Auth, tenancy, entitlements (auto-imported)
├── core/          # Layer 1 — Business domains: billing, catalog, team
└── product/       # Layer 2 — Product features: onboarding, analytics

common/            # Cross-cutting utilities (auto-imported)

Layer Dependency Rules

Strict import rules enforced by ESLint:

product/ → can import → core/, foundation/, common/
core/    → can import → foundation/, common/
foundation/ → can import → common/ only
common/  → imports NOTHING from features/

Violations the agent must reject: common/ importing from features/*, foundation/ importing from core/, core/ importing from product/, cross-imports between core features (except catalog).

API Call Pattern

The correct pattern for making API calls, enforced by ESLint rules:

// ❌ WRONG
const { data } = useFetch('/api/v1/subscription')

// ✅ CORRECT
const { data } = useAuthenticatedAsyncData(
  'billing:subscription',
  () => billingApi.getSubscription()
)

The flow: Page → Composable → useXxxApi() → common/api/client.ts

Auth (Sanctum cookies) and tenant context are not available during SSR. Raw useAsyncData without server: false will silently return null during SSR. The useAuthenticatedAsyncData wrapper forces client-side fetching for authenticated routes.

File Structure Per Feature

Every feature follows a consistent structure:

features/core/<feature>/
├── index.ts       # Public API (barrel exports) — REQUIRED
├── composables/   # Reactive logic
├── components/    # Vue components
├── api/           # API calls + Zod validation — core/product only
├── types.ts       # TypeScript types — REQUIRED
└── schemas.ts     # Zod schemas — REQUIRED

Additional Rules

  • Zod validation — All API responses must be validated with .parse()
  • useAsyncData keys — Namespaced: billing:subscription, catalog:plans
  • Composable returns — Return readonly() refs unless mutation is part of the API
  • Import rules — Foundation features are auto-imported; core/product use explicit barrel imports

For more on the frontend architecture, see Vertical Slices and Validation.


Progressive Disclosure Model

The configuration system uses a two-tier approach to manage context efficiently:

flowchart TD
    A["Tier 1 — Always Loaded<br/><br/>CLAUDE.md (root + backend or frontend as needed)<br/>~150-540 lines of essential context<br/>Project structure, commands, domain entities, conventions"] -->|"Developer invokes /docs/billing"| B["Tier 2 — On-Demand<br/><br/>.claude/skills/docs/billing/SKILL.md loaded<br/>Billing architecture, Stripe patterns, lifecycle rules,<br/>webhook handling, currency invariants, common mistakes"]

Why this matters: AI agents have context windows. Loading every convention document, every template, and every domain rule for every task wastes tokens and reduces response quality. Progressive disclosure keeps the base context lean (~150 lines at root level) while providing unlimited depth through the Skills System.

The base CLAUDE.md files answer: "Where does my code go? What are the naming conventions? What rules must I always follow?"

Skills answer: "How does billing work? What are the Stripe webhook patterns? How do I test tenant isolation? What are the currency invariants?"


Customizing for Your Project

When you add new domains to the boilerplate, keep the configuration files up to date.

Adding Domain Entities

When you create a new model, add it to the domain entities table in the root CLAUDE.md:

| **Notification** | Push/email notification with delivery tracking |

This ensures every AI agent session knows about the new entity.

Adding Critical Conventions

If your project has domain-specific rules that should always be loaded, add them to the "Critical Conventions" section:

### Analytics
- All tracking events must include `tenant_id` and `user_id`
- Event names use dot notation: `billing.subscription.created`
- Never track PII in event properties

What to Keep vs. Move to a Skill

Keep in CLAUDE.mdMove to a Skill
One-line rules (always snake_case)Multi-paragraph domain explanations
Directory structure and file locationsStep-by-step workflows
Command referenceCommon mistakes and anti-patterns
Entity list (name + one-line description)Full entity relationships and invariants
Keep the root CLAUDE.md under 200 lines. If a convention requires more than 5 lines of explanation, it belongs in a skill, not in the base configuration. See Skills System for creating domain-specific skills.

What's Next