Skip to main content

CLAUDE.md Conventions

The CLAUDE.md file is the instructions file that Claude Code reads automatically when starting a session in your project. It works as an onboarding manual for the AI: it tells it what stack you use, how the code is organized, what conventions to follow, and how to connect to external tools like Almirant.

A well-configured CLAUDE.md makes the difference between an AI that generates generic code and one that respects your team's architecture, patterns, and conventions.

Where to place the file

Place CLAUDE.md at the root of your repository:

your-project/
CLAUDE.md # <-- here
.claude/
skills/
settings.json
src/
package.json

Claude Code looks for this file automatically when opening the project. No additional configuration is needed.

Note

If you work with a monorepo, you can have a CLAUDE.md at the root and additional ones in subdirectories. Claude Code combines them all.

What to include when using Almirant

1. MCP configuration

The most important thing is that Claude Code knows how to connect to Almirant. Include the MCP server configuration with the URL and API key.

## MCP - Almirant

This project is connected to Almirant for task management.

Configuration in `.claude/settings.json` or `.mcp.json`:

\```json
{
"mcpServers": {
"almirant": {
"type": "http",
"url": "http://localhost:3001/mcp?projectId=<your-project-uuid>",
"headers": {
"Authorization": "Bearer <your-api-key>"
}
}
}
}
\```

Use MCP tools to read and update work items, boards, and sprints.
Tip

Reference the location of the MCP configuration, but never include the API key directly in CLAUDE.md. Use .claude/settings.json (which should be in .gitignore) or environment variables.

2. Project description

Provide general context about what the project is and what technologies it uses.

## Project description

B2B e-commerce web application built with:
- **Frontend**: Next.js 15 + React 19 + TypeScript + Tailwind CSS
- **Backend**: Bun + Elysia + Drizzle ORM
- **Database**: PostgreSQL 16
- **Auth**: Better-Auth with Google OAuth
- **Testing**: Vitest + Playwright

3. Repository structure

Explain how the code is organized so the AI can navigate efficiently.

## Structure

\```
src/
domains/ # Domain modules (DDD)
users/
domain/ # Types and interfaces
application/ # Hooks and use cases
presentation/ # Components and containers
orders/
products/
components/ui/ # Shared components (shadcn/ui)
lib/ # Utilities, API client, auth
\```

4. Code conventions

Define the rules Claude Code should follow when generating code.

## Conventions

- **Files**: kebab-case (`user-service.ts`, `order-form.tsx`)
- **Components**: PascalCase (`UserProfile`, `OrderList`)
- **Hooks**: camelCase with `use` prefix (`useUserProfile`, `useOrderList`)
- **No classes**: Use functional programming. Pure functions, custom hooks, functional objects
- **Types**: In `domain/types.ts`, not inside .tsx components
- **Components .tsx**: Presentational only. No useState, useEffect, or business logic
- **Logic**: In custom hooks inside `application/hooks/`

5. Project commands

Include the commands Claude Code may need to run.

## Commands

\```bash
bun run dev # Development server
bun run build # Production build
bun run lint # Linter
bun run test # Tests
bun run type-check # Type checking
bun run db:generate # Generate migration
bun run db:migrate # Apply migrations
\```

6. Code patterns

Document specific patterns you want the AI to replicate.

## Patterns

### API calls with React Query

All API calls use React Query with structured query keys:

\```typescript
export const userKeys = {
all: ['users'] as const,
list: (filters: UserFilters) => [...userKeys.all, 'list', filters] as const,
detail: (id: string) => [...userKeys.all, 'detail', id] as const,
};

export const useUsers = (filters: UserFilters) => {
return useQuery({
queryKey: userKeys.list(filters),
queryFn: () => usersApi.getAll(filters),
});
};
\```

### Mutations with invalidation

\```typescript
export const useCreateUser = () => {
const queryClient = useQueryClient();

return useMutation({
mutationFn: usersApi.create,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: userKeys.all });
},
});
};
\```

7. Project-specific rules

Include constraints or business rules the AI must respect.

## Rules

- **NEVER** execute SQL directly. Use Drizzle ORM + migrations
- **NEVER** commit .env files or credentials
- **NEVER** modify files in `migrations/meta/`
- Work items do NOT have a `status` column -- status is derived from the board column
- Work items use `archived_at` (timestamp) instead of a boolean for archiving
- Authentication uses `better-auth.session_token` cookies

Full example

# CLAUDE.md

## Project

B2B e-commerce for industrial product distribution.

**Stack**: Next.js 15 + React 19 + TypeScript + Tailwind CSS 4 + Elysia + Drizzle ORM + PostgreSQL 16

## MCP - Almirant

Task management via MCP. Configuration in `.mcp.json`.
Use MCP tools to read work items before implementing and
update status when finished.

## Structure

\```
src/
domains/ # DDD modules
catalog/ # Products and categories
orders/ # Orders and invoicing
customers/ # B2B clients
components/ui/ # shadcn/ui
lib/ # API client, auth, utils
\```

## Conventions

- Files in kebab-case
- Components: presentational only (no hooks in .tsx)
- Logic: custom hooks in application/hooks/
- Types: in domain/types.ts
- No classes: only functions, hooks, interfaces

## Commands

\```bash
bun run dev # Dev server (port 3000)
bun run build # Production build
bun run lint # ESLint
bun run test # Vitest
bun run db:generate # Generate migration
bun run db:migrate # Apply migrations
\```

## Patterns

### React Query

Structured query keys per domain.
Mutations invalidate related queries in onSuccess.

### API Client

Modules in lib/api/client.ts:
- catalogApi.getProducts(filters)
- ordersApi.create(data)
- customersApi.getById(id)

## Rules

- NEVER use direct SQL, always Drizzle + migrations
- NEVER commit .env
- Orders require stock validation before confirmation
- Prices calculated server-side, never trust the frontend

Advanced tips

Segment by audience

If your team includes different profiles (frontend, backend, devops), you can use sections with clear headings so each skill or workflow knows where to find relevant information.

Keep it up to date

Treat CLAUDE.md as living documentation. When you change a pattern, a convention, or the project structure, update the file. An outdated instruction can cause the AI to generate inconsistent code.

Don't document the obvious

There is no need to document how React or TypeScript works. Focus on what is specific to your project: internal conventions, custom patterns, business constraints.

Validate with your team

Just like skills, CLAUDE.md is versioned with Git. Review it in code review when there are significant changes to ensure the entire team is aligned.

Security

Never include credentials, API keys, tokens, or production URLs directly in CLAUDE.md. This file is versioned with Git and visible to the entire team. Use environment variables or configuration files in .gitignore.