Define Architecture
Define durable, easy-to-change architecture defaults for TypeScript apps.
How to use this skill
- Determine context:
- New codebase: follow
Architecture setup workflow.
- Existing codebase: follow
Adoption workflow.
- Produce an architecture brief using
Output template.
- Run
Validation loop before finalizing.
Load references only when needed:
- Stack defaults: references/stack-defaults.md
- Shipping and rollout: references/shipping-practices.md
- Engineering quality checklists: references/craftsmanship.md
Architecture setup workflow
- Define constraints first:
- Product scope, team size, compliance/security needs, expected scale.
- Deployment targets and required integrations.
- Choose repo shape:
- Use
apps/ for deployable surfaces (api, web, admin).
- Use
packages/ for shared libraries (shared, ui, icons, auth, proto).
- Define backend module contracts:
handler: transport only.
service: business orchestration.
dao: database access only.
mapper: DB/proto/domain transformations.
constants and types: module-local contracts.
- Define request context and middleware:
- Use AsyncLocalStorage-backed
RequestContext:import { AsyncLocalStorage } from "node:async_hooks";
type RequestContext = { tenantId: string; userId: string; traceId: string };
const store = new AsyncLocalStorage<RequestContext>();
export const getContext = () => store.getStore()!;
export const runWithContext = (ctx: RequestContext, fn: () => void) => store.run(ctx, fn);
- Initialize context in every entrypoint (RPC, HTTP, jobs, CLI).
- Read context via
getContext(); do not thread context params through business functions.
- Require route policy per RPC method and register services through
registerServiceWithPolicies.
- Keep auth, logging, errors, and context in shared middleware.
- Define frontend boundaries:
- Default to Server Components; add
"use client" only for client-only behavior.
- Use TanStack/Connect Query for server state.
- Use MobX only for cross-cutting client state that cannot live in component state.
- Keep forms, hooks, and UI mappings type-safe and implementation-focused.
- Define testing and release expectations:
- Backend TDD loop: Red -> Green -> Refactor.
- Unit tests stay DB-free; integration and E2E tests run in parallel with dynamic IDs.
- Release in small, reversible steps with a rollback plan.
Adoption workflow (existing codebase)
- Map current architecture and pain points.
- Select the smallest set of changes that enforce clear module boundaries.
- Migrate one vertical slice first.
- Add guardrails (lint/type/test checks) to prevent regression.
- Roll out module-by-module.
Stack defaults
Use references/stack-defaults.md as the default baseline. Deviate only when constraints require it.
Validation loop
Run this loop before finalizing architecture decisions:
- Verify consistency:
- Naming, module boundaries, and middleware rules are applied the same way across services.
- Verify quality gates:
npm run lint
npm run check-types
npm run test --workspace=<pkg> (or equivalent targeted tests)
- Verify operability:
- Observability, health checks, and rollback path are defined.
- If any check fails:
- Fix the architecture brief or conventions.
- Re-run the loop.
Output template
Use this structure for architecture recommendations:
# Architecture brief
## Context and constraints
## Repo shape
## Backend module contracts
## Request context and middleware policy
## Frontend boundaries
## Testing strategy
## Rollout and rollback plan
## Open risks and follow-ups
Skill handoffs
- Use
ui-audit for final UI quality checks.
- Use
ui-animation for motion-specific guidance.
Gotchas
- Don't default to microservices for teams under 5 — start with a modular monorepo and split later when boundaries are proven.
- Don't put app-level dependencies in root
package.json in a monorepo — each app owns its deps.
- Don't skip the adoption workflow for existing codebases — big-bang rewrites fail; migrate one vertical slice first.
- Don't define module contracts (handler/service/dao) without enforcing them via lint rules or type checks — unenforced contracts decay immediately.
- Don't over-abstract shared packages early — wait until three or more apps need the same code before extracting to
packages/.
- Don't skip the rollback plan — every architecture decision should be reversible or have a documented fallback.
1---2name: define-architecture3description: Generates folder structures, module contracts, middleware pipelines, and frontend/backend boundaries for TypeScript full-stack applications. Use when starting a project, setting up project structure, organizing a monorepo, configuring middleware, defining folder layout, designing backend modules, establishing team conventions, or asking "how should I structure this app", "design the folder structure", or "set up the architecture".4license: Unspecified5---6# Define Architecture78Define durable, easy-to-change architecture defaults for TypeScript apps.910## How to use this skill11121. Determine context:13 - New codebase: follow `Architecture setup workflow`.14 - Existing codebase: follow `Adoption workflow`.152. Produce an architecture brief using `Output template`.163. Run `Validation loop` before finalizing.1718Load references only when needed:19- Stack defaults: [references/stack-defaults.md](references/stack-defaults.md)20- Shipping and rollout: [references/shipping-practices.md](references/shipping-practices.md)21- Engineering quality checklists: [references/craftsmanship.md](references/craftsmanship.md)2223## Architecture setup workflow24251. Define constraints first:26 - Product scope, team size, compliance/security needs, expected scale.27 - Deployment targets and required integrations.282. Choose repo shape:29 - Use `apps/` for deployable surfaces (`api`, `web`, `admin`).30 - Use `packages/` for shared libraries (`shared`, `ui`, `icons`, `auth`, `proto`).313. Define backend module contracts:32 - `handler`: transport only.33 - `service`: business orchestration.34 - `dao`: database access only.35 - `mapper`: DB/proto/domain transformations.36 - `constants` and `types`: module-local contracts.374. Define request context and middleware:38 - Use AsyncLocalStorage-backed `RequestContext`:39 ```ts40 import { AsyncLocalStorage } from "node:async_hooks";41 type RequestContext = { tenantId: string; userId: string; traceId: string };42 const store = new AsyncLocalStorage<RequestContext>();43 export const getContext = () => store.getStore()!;44 export const runWithContext = (ctx: RequestContext, fn: () => void) => store.run(ctx, fn);45 ```46 - Initialize context in every entrypoint (RPC, HTTP, jobs, CLI).47 - Read context via `getContext()`; do not thread context params through business functions.48 - Require route policy per RPC method and register services through `registerServiceWithPolicies`.49 - Keep auth, logging, errors, and context in shared middleware.505. Define frontend boundaries:51 - Default to Server Components; add `"use client"` only for client-only behavior.52 - Use TanStack/Connect Query for server state.53 - Use MobX only for cross-cutting client state that cannot live in component state.54 - Keep forms, hooks, and UI mappings type-safe and implementation-focused.556. Define testing and release expectations:56 - Backend TDD loop: Red -> Green -> Refactor.57 - Unit tests stay DB-free; integration and E2E tests run in parallel with dynamic IDs.58 - Release in small, reversible steps with a rollback plan.5960## Adoption workflow (existing codebase)61621. Map current architecture and pain points.632. Select the smallest set of changes that enforce clear module boundaries.643. Migrate one vertical slice first.654. Add guardrails (lint/type/test checks) to prevent regression.665. Roll out module-by-module.6768## Stack defaults6970Use [references/stack-defaults.md](references/stack-defaults.md) as the default baseline. Deviate only when constraints require it.7172## Validation loop7374Run this loop before finalizing architecture decisions:75761. Verify consistency:77 - Naming, module boundaries, and middleware rules are applied the same way across services.782. Verify quality gates:79 - `npm run lint`80 - `npm run check-types`81 - `npm run test --workspace=<pkg>` (or equivalent targeted tests)823. Verify operability:83 - Observability, health checks, and rollback path are defined.844. If any check fails:85 - Fix the architecture brief or conventions.86 - Re-run the loop.8788## Output template8990Use this structure for architecture recommendations:9192```markdown93# Architecture brief9495## Context and constraints96## Repo shape97## Backend module contracts98## Request context and middleware policy99## Frontend boundaries100## Testing strategy101## Rollout and rollback plan102## Open risks and follow-ups103```104105## Skill handoffs106107- Use `ui-audit` for final UI quality checks.108- Use `ui-animation` for motion-specific guidance.109110## Gotchas111112- Don't default to microservices for teams under 5 — start with a modular monorepo and split later when boundaries are proven.113- Don't put app-level dependencies in root `package.json` in a monorepo — each app owns its deps.114- Don't skip the adoption workflow for existing codebases — big-bang rewrites fail; migrate one vertical slice first.115- Don't define module contracts (handler/service/dao) without enforcing them via lint rules or type checks — unenforced contracts decay immediately.116- Don't over-abstract shared packages early — wait until three or more apps need the same code before extracting to `packages/`.117- Don't skip the rollback plan — every architecture decision should be reversible or have a documented fallback.