BoilerplateHub

Agency Multi-Client AGENTS.md Template

For an agency repository where one core codebase powers multiple client sites or apps, with per client theming, content, and integrations. It assumes clients must stay isolated and that work is billable and scoped. Use it when the biggest risk is an agent changing shared code while working on one client.

TypeScriptNext.jsMonorepoCMSCI
AGENTS.md
Download
# AGENTS.md

This repository holds a shared core plus per client implementations. One core, many client deployments.

## Project

Stack: TypeScript, Next.js, pnpm workspaces, a headless CMS per client, per client environment configuration, GitHub Actions.

```
core/
  ui/            design system primitives, unbranded
  blocks/        composable page sections driven by CMS data
  lib/           integrations, CMS clients, analytics, forms
  config/        shared eslint, tsconfig, tailwind preset
clients/
  acme/          one directory per client
    app/         routes and pages
    theme.ts     tokens: colors, type scale, spacing
    config.ts    feature flags, integrations, locales
    content/     client owned copy and fixtures
    overrides/   client specific components that replace a core block
```

Client directories are named after the client slug and are the unit of deployment.

Entry points: `core/config/`, `clients/<client>/config.ts`, `clients/<client>/theme.ts`.

## Architecture

- A client never imports from another client. There is no shared "client utils" directory.
- `core/` never references a client by name. No `if (client === "acme")` anywhere in core.
- Customization happens in this order: theme tokens, then config flags, then a component in `overrides/`. Only if all three fail does core change.
- A core change must work for every client. If it cannot, it is a client override, not a core change.
- Adding a capability that two clients need means it goes into `core/blocks/` with a config flag, not copied twice.
- Client content lives in the CMS or in `clients/<client>/content/`, never hardcoded in a component.

## Commands

Every command targets a client.

```bash
pnpm install
pnpm --filter acme dev                 # run one client locally
pnpm --filter acme build
pnpm --filter acme test
pnpm --filter acme typecheck
pnpm --filter @core/ui test            # test shared code
pnpm lint                              # whole repo
pnpm build:all                         # build every client, run after any core change
pnpm --filter acme deploy:preview
```

A bare `pnpm dev` is not meaningful here. Always pass a client filter.

Environment files are per client: `clients/<client>/.env.local`.

## Code style

- No client name, client copy, or client asset inside `core/`.
- Colors, spacing, radii, and fonts come from `clients/<client>/theme.ts`. No raw hex values in a component.
- Feature differences are config flags in `clients/<client>/config.ts`, not conditionals in shared code.
- Core components accept props and slots. They do not read from a client config module.
- Overrides keep the same props contract as the core block they replace, so they stay swappable.
- Copy is never hardcoded in a component. Read it from CMS data or the client content directory.
- Third party scripts, pixels, and analytics are declared in client config and loaded through the core loader.
- Absolute imports through the workspace alias. No relative paths crossing a package boundary.

## Boundaries

Do not touch without explicit instruction:

- Any other client's directory when working on a scoped task. Stay inside the client you were asked about.
- `core/` when the task is a single client request. Propose the core change instead.
- Client credentials, API keys, CMS tokens, or `.env` files of any kind.
- Production CMS content and any live data.
- `.github/workflows/`, deployment configuration, DNS, and domain settings.
- `pnpm-lock.yaml`.

Needs human review: every change under `core/`, any new third party integration or tracking script, anything touching a client's payment, contact form, or consent handling, and any dependency upgrade.

If a client request seems to need a core change, write down the change, list which clients it affects, and stop.

## Testing

- `pnpm --filter <client> test` for client scoped work.
- A change under `core/` requires `pnpm build:all` plus the test suites of the smoke test clients listed in `core/SMOKE_CLIENTS.md`.
- Required tests: core blocks with logic, form handling, and every integration in `core/lib/`.
- Client code needs tests only where it contains logic. A themed page composition does not.
- Visual regression runs per client in CI. Do not accept new baselines without looking at the diff.

## Git workflow

- Branch as `client/<slug>/short-description` for client work, `core/short-description` for shared work.
- Conventional commits with the client or package as scope: `fix(acme): correct VAT display on invoices`, `feat(core-blocks): add pricing table variant`.
- Never mix a core change and a client change in one commit.
- PR title starts with the client slug or `core`. The description states which clients are affected and whether a redeploy is needed.
- A core PR lists the clients that were smoke tested.
- Never push to `main`.

What each section does

Project

Agency repos hide a hard rule in their structure: client directories are isolated and the core is shared. Writing out which directory belongs to which client, and where the core lives, is the difference between a scoped fix and an incident. It also tells the agent where per client configuration is expected to live.

Architecture

The whole model depends on clients never importing from each other and on the core never knowing about a specific client. That rule is invisible in any single file and easy to break with one convenient import. Documenting the override mechanism gives the agent a correct way to customize without forking.

Commands

Every command needs a client target, so an agent that runs a bare dev or build command is testing the wrong thing. Showing the client scoped forms prevents that. Deployment commands are included because each client ships separately.

Code style

The style rules that matter are about isolation: no hardcoded client names in core, configuration over conditionals, and tokens instead of raw values. These are all reviewable in a diff. Ordinary formatting is left to tooling.

Boundaries

Client credentials, CMS content, and production data belong to the client, not the repository, and must never be touched by an agent. Shared core changes affect every client at once and therefore need a person. Being explicit here is also a client trust matter.

Testing

A change to core needs verification across clients, not just the one in front of you. Saying which clients form the smoke test set makes that practical. Client specific code can carry lighter requirements than shared code.

Git workflow

Commits need to identify the client so billing, changelogs, and rollbacks are possible. A shared core change should be flagged in the PR so reviewers know the blast radius. Branch naming follows the same client first pattern.

Which agents read this file?

Claude Code looks for CLAUDE.md. Most other agents and editors read AGENTS.md. Rather than maintaining both and letting them drift, keep one real file and symlink the other:

ln -s AGENTS.md CLAUDE.md
git add AGENTS.md CLAUDE.md

Git stores the symlink, so it survives cloning on macOS and Linux. On Windows it needs developer mode or a stub file that references the real one. The full comparison is in CLAUDE.md vs AGENTS.md.

Other templates

Reviews

Leave a comment

Your rating (optional)

0/2000