Skip to content

16 — Contributing With The Architecture

Migrated from root technical docs.

Use this document when you are about to add new code.

It is the shortest path from:

  • “I need to add a page, feature, worker flow, or domain rule”
  • to the correct repo location, boundary, and starter pattern.

This guide does not replace the canonical architecture docs. It compresses them into a practical contribution workflow.

Related canonical docs:

See the copyable examples in templates/README.md.


These are the contribution rules that matter most.

  1. Organize product code by feature first.
  2. Keep routes thin. Route files declare, validate, preload, and hand off.
  3. Keep transport, query, mutation, model, and page composition separate.
  4. Reusable business logic belongs in domain packages, not pages or routes.
  5. Cloudflare runtime specifics stay behind server, worker, and infra layers.
  6. Shared UI stays primitive and generic. Business-named UI stays feature-owned.
  7. One feature has one source of truth. Do not add a parallel implementation.
  8. Do not create new junk-drawer folders such as helpers, common, shared, or broad utils without a narrow owner.
  9. Use the canonical docs before inventing a new structure.
  10. For new plan work, start from a GitHub issue, not an ad hoc local plan file.
  11. Run architecture validation before pushing: pnpm ci:arch.

If a change needs an exception, document it explicitly in the owning doc instead of silently drifting from the standard.


These are the places contributors are most likely to reintroduce architecture drift.

WorkflowMain regression riskUse this pattern
New dashboard page or routethick routes, duplicated query logic, page logic in route filesthin route + feature page
New dashboard feature slicemixed ownership, lib/ dumping, unclear internal structurefeature template
New query or mutationinline keys, ad hoc invalidation, direct server importsquery or mutation template
New shared UI primitivefeature imports leaking into shared UIshared UI checklist
New domain rule or policybusiness logic trapped in UI/server wiringdomain module template
New worker capabilityCloudflare runtime leaking into feature logicworker feature template
New docs or plandocs sprawl, mixed canonical and temporary notesdocs placement guide

The repo already has CI checks for structural regressions. These templates make the correct structure the default before CI has to reject anything.


Run this checklist before creating a file.

  1. Is this app wiring, feature code, shared UI, domain logic, platform logic, or runtime adapter code?
  2. Is this feature-specific, or truly shared across multiple owners today?
  3. Does this belong in a route, a feature, a domain package, a worker feature, or an infra adapter?
  4. Is this browser-safe, or does it touch Cloudflare runtime, auth sessions, D1, KV, queues, or worker env bindings?
  5. Am I creating a second source of truth for an existing feature?
  6. Am I about to add a generic folder name because ownership is unclear?
  7. If I move this later, would the target owner already be obvious now?

If any answer is unclear, stop and check:


GitHub-first workflow for plans and implementation work

Section titled “GitHub-first workflow for plans and implementation work”

Use this workflow when starting a new plan or a substantial implementation slice.

  1. Create a GitHub issue first.
  2. Capture both discovery and implementation phases in the issue.
  3. Create a dedicated branch for the issue before editing code or plan files.
  4. Add or update the plan under repository-root plans/ if the work needs a plan folder.
  5. Commit work to that branch with focused commits.
  6. Run the smallest relevant local validation first, then the repo validation required for the slice.
  7. Open a PR to main only after validation is green.

Minimum execution checklist:

  • GitHub issue exists
  • Discovery phase is described in the issue
  • Implementation phase is described in the issue
  • Branch created for the issue
  • Relevant docs and plan files updated
  • Validation or CI commands run locally
  • PR opened to main

Recommended validation commands before opening the PR:

Terminal window
pnpm ci:arch
pnpm lint
pnpm type-check
pnpm validate

Use narrower commands first when the change is localized, but do not open the PR with known failing required checks.


If you are adding…Put it here
Dashboard route declarationapps/dashboard/src/routes/{-$locale}/...
Dashboard page entryapps/dashboard/src/features/{feature}/pages/
Feature UIapps/dashboard/src/features/{feature}/components/ or packages/feature-*/src/components/
Feature query keys or query optionsowning feature query-keys.ts and queries.ts
Feature mutation hooksowning feature mutations.ts
Feature model logicowning feature model/
Shared low-level UI primitiveapps/dashboard/src/shared/ui/
Shared business rulepackages/domain-*/src/
Cloudflare worker application logicworkers/*/src/features/
Cloudflare adapters or binding accessworkers/*/src/infra/ or apps/dashboard/src/server/
Canonical architecture or placement docdocs/architecture/
ADRdocs/adr/
Runbookdocs/runbooks/
Active planplans/{plan-slug}/

Do not add new production code to deprecated workers/my-api/.


  1. Create or extend the owning feature under src/features/ or the owning packages/feature-* package.
  2. Keep the route file thin.
  3. Put page composition in pages/.
  4. Put server state in queries.ts and mutations.ts.
  5. Put mapping, filters, and validation helpers in model/.

Start from:

Add a query and mutation to an existing feature

Section titled “Add a query and mutation to an existing feature”
  1. Add or extend query-keys.ts.
  2. Add queryOptions(...) factories in queries.ts.
  3. Keep raw write calls in api.ts.
  4. Wrap writes in useMutation with explicit invalidation in mutations.ts.

Start from:

  1. Confirm it is generic and low-level.
  2. Confirm it does not import feature code.
  3. Use generic naming such as Button, Card, Dialog, Tabs.
  4. If the component is business-named, keep it in the owning feature.

Start from:

  1. Keep it framework-light and runtime-light.
  2. Export pure functions, validators, policies, or interfaces.
  3. Do not import React, routes, server function wrappers, or Cloudflare env.

Start from:

  1. Put orchestration in features/{domain}/.
  2. Keep runtime binding access in infra/.
  3. Keep the worker entrypoint thin.
  4. Use shared/ only for narrow worker-safe helpers and types.

Start from:

  1. Decide whether the doc is canonical, operational, temporary, or local-only.
  2. Put it in the correct docs section immediately.
  3. Link local-only docs from docs/README.md if they need discoverability.

Start from:

  1. Create the GitHub issue first.
  2. Add discovery and implementation phases to the issue body.
  3. Create a branch for the issue.
  4. Create the plan at repository-root plans/{plan-slug}/.
  5. Link the issue from the plan and the plan from the issue.
  6. Commit the initial plan on the issue branch.
  7. Run validation before opening the PR to main.

Start from:


  • Do not put business logic in route files.
  • Do not put feature logic in src/shared/ or src/lib/.
  • Do not put worker logic in dashboard code.
  • Do not put Cloudflare env access in browser-safe layers.
  • Do not add helpers.ts, common.ts, shared.ts, or broad utils.ts files when a narrower owner exists.
  • Do not add a second implementation of an existing feature in a different package or app folder.
  • Do not promote a feature component into shared UI just because two call sites happen to use it.
  • Do not statically import server function modules from client-safe code.

For common addition paths, use the scaffold script:

Terminal window
pnpm scaffold dashboard-feature my-feature
pnpm scaffold dashboard-feature my-feature --route my-feature
pnpm scaffold domain-module my-domain
pnpm scaffold worker-feature worker-ingestion-process linking

Expected output paths:

  • dashboard-featureapps/dashboard/src/features/{feature}/... plus optional route files in apps/dashboard/src/routes/{-$locale}/(dashboard)/...
  • domain-modulepackages/domain-{name}/src/...
  • worker-feature worker-ingestion-process {feature}workers/ingestion-process/src/features/{feature}/...
  • shared ingestion runtime modules → packages/platform-ingestion/src/features/{feature}/...

Use --dry-run first if you want to inspect the output without writing files.

The script creates small starter files only. It does not try to guess complex business logic or own generated artifacts.


Run the smallest relevant checks, then run architecture validation.

Terminal window
pnpm ci:arch
pnpm lint
pnpm type-check

Also run any feature-level or worker-specific validation needed for your slice. See 15-architecture-checks.md for what CI will enforce.

For plan-driven work, make sure the PR points back to the GitHub issue and the issue already contains the discovery and implementation phases.


These are real and documented. Do not copy them into new code unless the same exception is explicitly accepted.

  1. workers/consumer-api/src/index.ts is still a documented monolith. New worker work should follow the worker structure guide instead of copying that layout.
  2. workers/rate-limiter remains a single-file Durable Object because the worker is intentionally small.
  3. Some dashboard data layers live in packages/feature-* while page composition remains app-local. Follow the feature source-of-truth doc instead of assuming every dashboard feature is app-local.
  4. Root plans/ is deprecated. New plans go in docs/plans/.

When you encounter another exception, document why it differs and whether it is legacy-only or acceptable for new code.