Methodology - Agent Conventions

AGENTS.md + CLAUDE.md: how this repo steers coding agents.

A convention emerging across the agentic-coding ecosystem: two markdown files at the repo root that tell agents (Claude Code, Codex, Cursor, and any others that read them) what this project is, how it builds, what conventions to follow, and what NOT to do. This page documents the convention and publishes the exact files this site ships so you can copy the pattern.

ConventionRepo rootCoding agents

What AGENTS.md is

AGENTS.md is a short, repo-root markdown file that announces project-wide ground rules every coding agent should respect on every turn. The audience is agents, not humans - think of it as the file you would hand a brand-new contractor on day one if that contractor was a language model. The convention is intentionally tool-neutral: Claude Code reads it, Codex CLI reads it, and any agent that has been taught to look for it reads it.

The most common content is a single sentence per rule: breaking changes in your stack, version-pinned APIs to avoid, files to never edit, conventions that are non-obvious from code. ACP's AGENTS.md focuses on the "this is NOT the Next.js you know" warning - because Next 16 has breaking changes from the training data most models were exposed to.

What CLAUDE.md is

CLAUDE.md is the Claude-specific companion to AGENTS.md. It expands the AGENTS.md ground rules with Claude-specific guidance: the file convention @AGENTS.md at the top of CLAUDE.md tells Claude Code to load AGENTS.md first, then layer the Claude-specific rules on top. The pattern lets generic rules live in AGENTS.md (any agent reads them) and Claude-specific guidance live in CLAUDE.md (only Claude reads it).

ACP's CLAUDE.md documents the full Next 16 + Convex + Clerk + Resend + OpenRouter stack, the secrets-boundary rule (browser never holds a secret), MCP rules, and the auth-gating contract. None of this is derivable from code alone, which is why it must live in CLAUDE.md.

Why both files live at the repo root

Both files live at the repo root because coding agents start their context-window walk at the working directory and look up the tree. A file at the repo root is the first thing read on every cold start, and it stays in context for the rest of the turn. Putting these files anywhere else (a docs subdirectory, a wiki) breaks the convention: the agent never sees them.

If you want to scope rules to a specific subdirectory, drop another CLAUDE.md inside that subdirectory. The agent layers the deeper file on top of the root file - the deeper rules win on conflicts.

The AGENTS.md this site ships

Below is the verbatim content of AGENTS.md at the root of the claudearchitectcertification repo, read at build time:

<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->

<!-- convex-ai-start -->

This project uses [Convex](https://convex.dev) as its backend.

When working on Convex code, **always read
`convex/_generated/ai/guidelines.md` first** for important guidelines on
how to correctly use Convex APIs and patterns. The file contains rules that
override what you may have learned about Convex from training data.

Convex agent skills for common tasks can be installed by running
`npx convex ai-files install`.

<!-- convex-ai-end -->

The CLAUDE.md this site ships

Below is the verbatim content of CLAUDE.md at the root of the same repo, read at build time:

@AGENTS.md

# CLAUDE.md — claudearchitectcertification.com

## Repository Overview
ACP (AI Certification Prep Platform) — Next.js 16 App Router app deployed on Vercel, backed by Convex (DB + scheduler + actions + crons + HTTP webhooks), Clerk auth (Phase 4), Resend email (Phase 4), OpenRouter LLM (cached, Phase 4), MDX-in-repo blog, Orama client-side search, Vercel Analytics. Domain: claudearchitectcertification.com.

Mirror of source-of-truth specs in The Construct vault at `~/Documents/The_Construct/02_Tasks/`:
- ACP-T04 v4 — system architecture, IA, gating, AEO
- ACP-T11 — this repo's setup spec (with §A-§F local + cloud + CLAUDE.md + services + MCP test + Convex migration appendix)
- ACP-T12 — Phase 4 auth + gating + adaptive plan
- ACP-T13 — Phase 5 question bank generation
- ACP-T14 — BRD (12-section consolidating doc, 4 personas, 5 user stories, NFRs, KPIs, risks, glossary)
- ACP-T15 — master feature list (8 stages, ~80 features w/ FE-XX.XX IDs, acceptance criteria, telemetry events)
- DEC-202604291030 — stack pivot decision

## Tech Stack
- **Frontend:** Next.js 16 (App Router, RSC) + React 19 + TypeScript + Tailwind CSS v4
- **Backend:** Convex (TS schema, mutations, queries, actions, crons, HTTP actions) — Phase 4
- **Auth:** Clerk (Convex JWT bridge via `<ConvexProviderWithClerk>`) — Phase 4
- **Email:** Resend via `@convex-dev/resend` — Phase 4
- **LLM:** OpenRouter via Convex action (cheap default, e.g. `anthropic/claude-haiku-*`) — Phase 4
- **Search:** Orama client-side bundle (build-time index from MDX) — Phase 3
- **Analytics:** Vercel Analytics (live in Phase 2) + optional Plausible
- **Commerce:** Razorpay (India) + Dodo Payments (international MoR) — Phase 7

## Key Commands
| Command | Purpose |
|---|---|
| `pnpm dev` | Local Next.js dev server (port 3000) |
| `pnpm dev:convex` | Local Convex dev server (port 6790 dashboard) |
| `pnpm build` | Production build |
| `pnpm typecheck` | `tsc --noEmit` strict |
| `pnpm lint` | ESLint |
| `pnpm search-index` | Build Orama search index from MDX content |
| `npx convex env set KEY VALUE` | Set Convex env var |
| `npx convex deploy` | Manual Convex prod deploy (Vercel auto-runs on `git push`) |

## Architecture Pattern (per ACP-T04 v4 §9.2)
Browser → Vercel edge (middleware.ts JWT check, Phase 4) → Server Components → Convex client → Convex server (mutations / queries / actions) → external APIs (OpenRouter, Resend, Razorpay, Dodo).

## File Conventions
- `app/` — Next.js App Router routes (server components default; `"use client"` only when needed)
- `app/blog/{slug}/page.mdx` — MDX blog posts (Phase 2 convention; Phase 3 may shift to `/content/blog/` walker)
- `components/` — reusable UI; `components/templates/` for the 15 page templates A-O (Phase 3)
- `convex/` — schema, mutations, queries, actions, crons, HTTP webhooks (Phase 4)
- `lib/` — pure utilities (no Convex / Next.js imports)
- `scripts/` — build-time scripts (Orama index, Q-bank loader, etc.)

## API Endpoint Conventions
Convex over Next.js API routes. Webhooks at `https://{deployment}.convex.site/webhooks/{provider}`. Only `/api/healthz` lives in Next as a static route.

## Auth + Gating Rules (Phase 4)
- Edge `middleware.ts` matches `/practice/mock(.*)` and `/account(.*)`; redirects unauth to `/sign-in?next=...`
- Server enforcement: `examAttempts.start` mutation throws `Limit reached` if `attemptCount >= 3 && paidAttemptCredits == 0`
- UI hiding is UX layer only — never trust the UI alone
- All gated routes are `Disallow:` in `app/robots.ts`

## Secrets Boundary (CRITICAL ARCHITECTURAL RULE)

**The browser never holds a secret.** Every secret-bearing API call goes through Convex (server-side). Three tiers, hard rules.

### Three storage tiers
- **Tier 1 — Convex env** (`npx convex env set`) — for any key authenticating an outbound API call from server code. Browser never sees these. Examples: `OPENROUTER_API_KEY`, `RESEND_API_KEY`, `RAZORPAY_KEY_SECRET`, `RAZORPAY_WEBHOOK_SECRET`, `DODO_API_KEY`, `DODO_WEBHOOK_SECRET`, `CLERK_WEBHOOK_SECRET`.
- **Tier 2 — Vercel env, server-only (no `NEXT_PUBLIC_` prefix)** — for secrets needed by Next.js server components, route handlers, or middleware. Stripped from client bundle by Next.js build. Examples: `CLERK_SECRET_KEY`, `CONVEX_DEPLOY_KEY` (prod scope), `CONVEX_DEPLOY_KEY` (preview scope).
- **Tier 3 — Vercel env, public (`NEXT_PUBLIC_*` prefix)** — publishable values vendors design to be browser-visible. NOT secrets. Examples: `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY`, `NEXT_PUBLIC_CONVEX_URL`, `NEXT_PUBLIC_RAZORPAY_KEY_ID`.

### Hard rules
1. **Browser code never imports** any module that reads a Tier-1 or Tier-2 variable. The `NEXT_PUBLIC_` prefix is the ONLY signal a value is safe for the client bundle.
2. **All payment/email/LLM API calls flow through Convex.** Next.js API routes are reserved for `/api/healthz` only. New non-public surfaces become Convex mutations / actions / HTTP actions.
3. **Webhook secrets stay in Convex env**, NOT Vercel — webhooks land at `https://{deployment}.convex.site/webhooks/*`, not at Next.js API routes.
4. **`.env.local` is git-ignored**. Contains only what's needed to run `pnpm dev` + `npx convex dev` locally; nothing in it is shared between developers.
5. **One-time content-prep secrets** (e.g. `ANTHROPIC_API_KEY` for ACP-T13 synthetic Q generation) live ONLY in local `.env.local` and never deploy.
6. **PR review requires** updating the secrets table in `02_Tasks/ACP-T04_Site_IA_and_Page_Templates.md` §9.7.0 when adding any new secret.

### Anti-patterns (lint-blockable)
- ❌ `import OpenAI from "openai"` in `app/` or `components/`
- ❌ `import { Resend } from "resend"` in `app/` or `components/`
- ❌ `import Razorpay from "razorpay"` in `app/` or `components/` (only the publishable key + browser SDK go in `app/`; the server SDK lives in `convex/`)
- ❌ `process.env.OPENROUTER_API_KEY` outside `convex/`
- ❌ Adding a `NEXT_PUBLIC_*KEY*` variable that isn't a publishable / URL-only value

### Verification
```sh
# Verify no NEXT_PUBLIC_ variable carries a real secret pattern
grep -r "NEXT_PUBLIC_.*KEY" app/ components/ | grep -v "PUBLISHABLE\|RAZORPAY_KEY_ID\|CONVEX_URL"
# Should return zero matches.
```

**Authoritative table:** `02_Tasks/ACP-T04_Site_IA_and_Page_Templates.md` §9.7.0 Secrets Boundary — single source of truth for every secret's tier classification.

## MCP Rules
- **Exa MCP** is for RESEARCH ONLY (verifying current vendor docs, competitor analysis). Never as runtime dependency. Never from app code.
- **Playwright MCP** for E2E testing in dev. Never in app runtime.
- **Context7 MCP** for library lookup during development. Not in app runtime.

## Lint + Formatting
- ESLint with Next.js + TypeScript strict
- Pre-commit: `pnpm lint && pnpm typecheck` must pass (enforced by Husky
  hook at `.husky/pre-commit`; install runs automatically on `pnpm install`
  via the `prepare` script)
- React 19's new hook-perf rules (`react-hooks/set-state-in-effect`,
  `react-hooks/purity`, `react-hooks/rules-of-hooks`, `react-hooks/use-memo`)
  are downgraded to warnings until legacy components are refactored
  (SCRUM-185). New code should still avoid these patterns.
- Vendored artifact dirs are excluded from lint + typecheck:
  `docs/**` (Leaderboard vite sandbox), `data/**` (AEO capture payloads),
  `scripts/aeo/**` (Playwright scripts), `.claude/**` (agent worktrees).
  If you need to typecheck a script ad-hoc, run it directly with `tsx`.
- Vale lint for content (config in `.vale.ini` per ACP-T04 v4 §5.1) — added in Phase 6

## Domain Concepts (see ACP-T14 BRD §13 Glossary)
- **CCA-F** — Anthropic Claude Certified Architect Foundations (60 Qs, 720/1000 pass)
- **5 domains** — D1 (27%) D2 (18%) D3 (20%) D4 (20%) D5 (15%)
- **3-attempt lifetime cap** — server-enforced in `examAttempts.start`
- **Tier-1 / Tier-2 plan** — deterministic + cached LLM narrative
- **Order-independent cache key** — SHA-256 of sorted `(qid, ai)[]`
- **9-pillar IA** — 138 routes (entry/curriculum/concepts/scenarios/knowledge/practice/exam-guide/reference/evidence) + blog
- **4 personas** — Admin (A), Anonymous (B), Authenticated (C), Paying (D)

## Workflow Reminders for Claude Code
- Use TaskCreate for multi-step work
- Edit existing files; never create parallel docs
- Server-enforce all gating; UI is UX layer
- Telemetry events fire from server (Convex) AND client (Plausible) when both layers are needed
- Run `pnpm typecheck && pnpm lint` before any commit
- Verify `git status` is clean and on correct branch before pushes
- Heed Next 16 deprecations (per AGENTS.md) — read `node_modules/next/dist/docs/` before adopting unfamiliar APIs

<!-- convex-ai-start -->

This project uses [Convex](https://convex.dev) as its backend.

When working on Convex code, **always read
`convex/_generated/ai/guidelines.md` first** for important guidelines on
how to correctly use Convex APIs and patterns. The file contains rules that
override what you may have learned about Convex from training data.

Convex agent skills for common tasks can be installed by running
`npx convex ai-files install`.

<!-- convex-ai-end -->

How to copy the pattern for your repo

  1. Create AGENTS.md at the repo root. List the framework version, the top 3 breaking-change traps, and any files agents must never edit.
  2. Create CLAUDE.md at the repo root. Open with@AGENTS.md on the first line so Claude Code inherits the general rules.
  3. Layer in your Claude-specific guidance: stack overview, key commands, file conventions, secrets boundary, anti-patterns to avoid.
  4. For subdirectory-scoped rules, drop another CLAUDE.md inside that subdirectory. Deeper rules override root rules on conflict.

Last updated

Up next: the broader methodology hub that explains the evidence tiers, refresh cadence, and corrections protocol behind every claim on this site.