Audience: every AI coding agent that operates in this monorepo — Claude Code, Cursor, GitHub Copilot, Codex, Gemini Code Assist, Aider, Continue, Cline, Roo, etc. Human contributors should follow the same rules for consistency.
The web app lives at
apps/web/. The Playwright suite lives atapps/web-e2e/. The Docusaurus docs site lives atapps/docs/. Shared configs live inpackages/.
These files form the canonical rule set for this repo:
.specify/memory/constitution.md— durable principles. Every plan must pass the Constitution Check..specify/README.md— Spec Kit workflow.docs/spec/README.md— feature spec index.docs/index.md— end-user home page.docs/agents-and-contributors.md— agent onboarding + per-source-file / spec / plugin reference index. New spec / plugin / config reference pages link from here, not fromdocs/index.md.docs/log.md— running log of changes.docs/questions.md— open questions and chosen defaults awaiting maintainer review.CLAUDE.md— Claude-specific guidance (commands, env vars, conventions). Most of it applies to every agent.README.md— repo overview.
If a rule below conflicts with the constitution, the constitution wins.
⚠️ Definition of Done — applies to every non-trivial PR.A change is NOT done until ALL of these are true. CI does not enforce them yet; agents and reviewers MUST self-enforce.
- Spec exists under
docs/spec/NNN-<slug>/spec.mdcovering what and why (status: shipped / in-progress / proposed).- If the change is architecturally meaningful (new route, new surface, new API, new contract), a
plan.mdexists too.docs/spec/README.mdindex has a row for the new spec.docs/log.mdhas a dated entry naming the spec, the area (spec-NNN,apps/web/...), and the PR number(s).docs/questions.mdhas an entry for every open decision the spec defers, with a chosen default so work is not blocked.Trivial-fix exception. Typos, broken links, dependency bumps with no API change: skip steps 1–3, write only the
docs/log.mdline.Why this is loud. May 2026 we shipped 9 PRs (#777 → #803, including a 3.7 MB → 50 KB perf win and a silent category-state bug fix) without a single spec or log entry. Catch-up cost two additional PRs (#804 → #806) plus the cognitive tax of reverse- engineering intent from PR descriptions. Spec/log alongside code is cheaper than spec/log retrofitted.
The standard Spec Kit flow is:
- Spec (
docs/spec/NNN-feature-slug/spec.md) — describe what and why, not how. - Plan (
docs/spec/NNN-feature-slug/plan.md) — design the how. Includes a Constitution Check section. - Tasks (
docs/spec/NNN-feature-slug/tasks.md) — break the plan into verifiable, parallelisable items. - Implement the tasks one by one. Each task ends in a verification step.
- Document the change in
docs/, link the spec, and append a line todocs/log.md. This step is not optional — see the Definition of Done above.
For multi-PR features (e.g. an initial spec landed in PR #N then
follow-ups #N+1, #N+2 fix regressions or extend scope), each follow-up
PR appends a docs/log.md line referencing the same spec-NNN and
notes what changed in the spec body. Do not start a new spec number
for incremental follow-ups to the same feature.
Almost everything is a plugin or adapter:
- New features default to a new package under
packages/<name>/that implements an interface from@ever-works/plugin-sdk(see Spec 002). - Core code (router shell, theme provider, i18n loader, plugin registry, CMS schema) is the only thing that lives outside packages.
- Core must not import from plugin packages — plugins are wired in through the runtime registry. ESLint enforces this once the SDK ships.
- Every UI feature should be expressible as a slot so end users can toggle / replace it without editing layouts.
- Every plugin must declare a Zod config schema and validate at boot. Config precedence: env vars < DB row < explicit override.
- Plugins must be enable / disable / swap / replace-able.
- All production source is
.ts/.tsx. - Scripts use
tsx. No new.js,.cjs,.mjsfiles unless required by tooling and documented indocs/architecture/. - No Python or Bash beyond simple CI glue.
anyis allowed only with an inline comment explaining why and a TODO link to a follow-up spec.
- LCP ≤ 2.5s, INP ≤ 200ms, CLS ≤ 0.1 on representative public pages.
- Public routes ≤ 250 KB gzip first-load JS.
- Admin lists with ≥ 200 rows must virtualise.
- DB access goes through a repository in
apps/web/lib/repositories/**. N+1 is a blocker. - Default to React Server Components; opt into client components only when interactivity is required.
- Next.js, React, TypeScript, Tailwind CSS, ESLint, Drizzle, Playwright, Docusaurus, HeroUI, Auth.js, next-intl, Turborepo, pnpm — all on latest stable unless a spec documents the exception.
- Major upgrades land via
docs/spec/NNN-upgrade-<framework>/with a migration plan.
- Check
packages/before authoring a new utility. - Check the npm ecosystem before authoring a new internal package.
- Prefer popular, well-maintained, TypeScript-first, ESM libraries.
- Document the choice in the relevant
plan.md.
- Move and improve, don’t delete. Renaming is fine.
- Hard-deleting a feature requires
docs/spec/NNN-deprecate-<feature>/spec.mdwith impact, replacement, deprecation timeline, and migration steps. - Existing e2e specs that document behaviour stay until a deprecation spec ships.
- Every user-visible change ships with at least one Playwright spec
under
apps/web-e2e/tests/<area>/. - Every new API route ships with at least one Playwright API spec
under
apps/web-e2e/tests/api/. - Authenticated flows reuse the storage states from
global-setup.ts. - Tests assert on roles / labels /
data-testid, not on copy that changes with content.
- Every feature has a page under
docs/that is reachable fromdocs/index.md— directly for end-user feature pages, or viadocs/agents-and-contributors.mdfor per-source-file / spec / plugin reference pages. - Index-bullet descriptions stay to one line — the linked page holds
the detail. Do not paste reference summaries / failure matrices /
checklists into the bullet itself; that bloated
docs/index.mdto 1.1 MB and broke the home page in May 2026. - Every plugin ships with a
README.mdinside its package and a feature page underdocs/features/ordocs/plugins/. - Open questions go to
docs/questions.mdwith a chosen default so work is not blocked. - Significant changes append a line to
docs/log.md. - Docs are lint-clean: frontmatter present, no broken internal links, no orphan files.
- Each package fits in a developer’s head (typically ≤ ~2k lines).
- Public surface declared via
package.json#exports. - Cross-package coupling goes through public exports only.
- Cross-cutting concerns (logging, telemetry, errors) live in dedicated packages, not duplicated.
Use these commands (see CLAUDE.md for the full list):
pnpm run dev– start all dev servers (from monorepo root).pnpm run --filter @ever-works/web dev– start only the web app.pnpm run build– build all packages.pnpm run lint– lint all packages.pnpm tsc --noEmit– TypeScript type-check (run fromapps/web/).pnpm --filter @ever-works/web-e2e exec playwright test– run e2e suite locally.
Treat as the main verification steps:
- For quick checks:
pnpm lintandpnpm tsc --noEmit. - For larger changes: also
pnpm buildand a relevant Playwright spec.
Run commands from the monorepo root. App-specific commands
(pnpm db:migrate etc.) can be run from apps/web/.
- Assume
.env.localalready exists and is correctly configured. - Do not create, modify, or print env secrets unless the user explicitly asks.
- Content is loaded from the Git-based CMS repo pointed to by
DATA_REPOSITORY(Spec 006).
Always safe to run:
pnpm lintpnpm tsc --noEmitpnpm buildpnpm dev/pnpm start(local verification)pnpm --filter @ever-works/web-e2e exec playwright test
Ask the user first before:
- Adding new dependencies (
pnpm add). - Running migrations or seeds against any non-local DB.
- Modifying
.env*semantics. - Changing auth, payments, analytics integrations beyond what a spec authorises.
- Pushing to
main(always go via PR).
Never do:
- Skip git hooks (
--no-verify). - Force-push to
main/develop. - Delete branches, tags, or files outside the documented scope.
- Modify or commit secrets (
.env.local, API keys).
- Next.js App Router under
apps/web/app/[locale]/**andapps/web/app/api/**. - Shared business logic in
apps/web/lib/services/**andapps/web/lib/repositories/**. - Database schema and helpers in
apps/web/lib/db/**(Drizzle ORM). - UI and layout components in
apps/web/components/**. - Custom React hooks in
apps/web/hooks/**.
When implementing features:
- Put domain / business logic in
lib/**. - Keep React components focused on rendering and wiring.
- Put cross-cutting code into a
packages/<name>/package.
Some scheduled tasks (see .claude/scheduled-tasks/full-template/)
operate on this monorepo every hour with a continuous-improvement
charter. Within this monorepo only, those runs may:
- Add or improve docs and specs.
- Add or improve e2e tests.
- Plan plugin / adapter refactors and document them in
docs/spec/NNN-<slug>/. - Open questions in
docs/questions.mdwith a chosen default. - Append a
docs/log.mdline. - Commit and push to the template repo.
Those runs must not:
- Modify anything outside
directory-web-template/. - Delete features, specs, or docs (Article VIII of the constitution).
- Bypass git hooks.
- Land code without a spec/plan/tasks trio (Article III).
README.md— repo overview.CLAUDE.md— Claude-specific guidance.apps/web/README.md— web app setup.apps/web-e2e/E2E-TESTS.md— coverage matrix.packages/— shared configs and (eventually) plugin packages.- External docs repo (platform-wide): https://github.com/ever-works/ever-works-docs/tree/develop/website/docs.