docs: add building-feature-ui guide and update agent instructions
Some checks failed
CI / typecheck + lint + boundaries + test + build (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Coverage snapshot / snapshot (push) Has been cancelled
Release Please / release-please (push) Has been cancelled
Sentry PII guard (R31) / pii-guard (push) Has been cancelled
CI / Playwright e2e (push) Has been cancelled
CI / Storybook smoke tests + visual regression (push) Has been cancelled
Mutation testing (nightly) / mutate (push) Has been cancelled
Some checks failed
CI / typecheck + lint + boundaries + test + build (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Coverage snapshot / snapshot (push) Has been cancelled
Release Please / release-please (push) Has been cancelled
Sentry PII guard (R31) / pii-guard (push) Has been cancelled
CI / Playwright e2e (push) Has been cancelled
CI / Storybook smoke tests + visual regression (push) Has been cancelled
Mutation testing (nightly) / mutate (push) Has been cancelled
- New guide covers server/client component pattern, hooks, DI prefetch, HydrationBoundary hydration, core-ui atomic design reuse, Tailwind wiring, seed data, and cross-feature boundaries - Update AGENTS.md with feature UI folder structure and naming rules - Update CLAUDE.md with feature UI data fetching convention
This commit is contained in:
@@ -59,6 +59,7 @@ Turborepo + pnpm monorepo organized by vertical features. Each feature (`auth`,
|
||||
- `docs/guides/coverage.md` — 4-layer coverage cookbook (L0 vitest thresholds, L1 `pnpm coverage:diff`, L2 aggregate, L3 mutation; ADR-020)
|
||||
- `docs/guides/releasing.md` — release-please workflow: how Conventional Commits become tagged versions + per-package CHANGELOGs (ADR-021)
|
||||
- `docs/architecture/template-tiers.md` — must-have vs optional packages and how to scaffold the optionals
|
||||
- `docs/guides/building-feature-ui.md` — Feature UI components, hooks, data fetching (tRPC + React Query), SSR prefetch/hydration, seed data, DI wiring
|
||||
- `docs/guides/compliance-overview.md` — hub for operator compliance obligations: GDPR, cookie consent, DSR, and pre-launch checklist
|
||||
|
||||
## Conformance system
|
||||
@@ -105,7 +106,8 @@ See `docs/guides/coverage.md` for the cookbook and ADR-020 for the full rational
|
||||
- **Schemas in the use-case file** — Every use case exports `xInputSchema` (a `z.ZodObject` with `.strict()`; `z.object({}).strict()` for void inputs) and, for non-void use cases, `xOutputSchema`. Types: `XInput = z.infer<typeof xInputSchema>` and `XOutput`. Use case body ends with `xOutputSchema.parse(result)` before returning (runtime guarantee against malformed repository data)
|
||||
- **Controllers receive `unknown` + presenter** — Controllers `safeParse(xInputSchema)` from the use-case file and throw `InputParseError` on failure. Non-void controllers define a top-level `function presenter(value: XOutput)` and return `Promise<ReturnType<typeof presenter>>` (identity is fine — `return value`); void controllers return `Promise<void>` with no presenter
|
||||
- **Feature-scoped tRPC error mapping** — Each feature has `integrations/api/procedures.ts` exporting `xProcedure = t.procedure.use(defineErrorMiddleware([[Ctor, "TRPC_CODE"], ...]))` from `@repo/core-shared/trpc/define-error-middleware`. Routers use `xProcedure.input(xInputSchema)` — schemas are imported from the use-case file, never redefined inline. `core-shared` never enumerates feature error classes
|
||||
- **Public surface split** — Feature root (`.`) exports contracts only: types, errors, schemas, IUseCase / IController aliases, router type, constants. UI artifacts (query builders, components) live behind `./ui` (`src/ui/index.ts`). Apps import queries from `@repo/<feature>/ui`, schemas/types from `@repo/<feature>`
|
||||
- **Public surface split** — Feature root (`.`) exports contracts only: types, errors, schemas, IUseCase / IController aliases, router type, constants. UI artifacts (hooks, components, query builders) live behind `./ui` (`src/ui/index.ts`). Apps import hooks/components from `@repo/<feature>/ui`, schemas/types from `@repo/<feature>`
|
||||
- **Feature UI owns its data fetching** — Each feature's `src/ui/hooks/` contains `"use client"` hooks that wrap `useTRPC` + `useSuspenseQuery`. Connected components in `src/ui/components/` call these hooks. App pages prefetch via `appRouter.createCaller({})` and hydrate via `HydrationBoundary` + `dehydrate` + `setQueryData`. See `docs/guides/building-feature-ui.md`
|
||||
- **Payload repositories via constructor** — Feature packages receive Payload config at constructor time, not as a direct dependency
|
||||
- **Three binding modes per feature** — Each feature exports two binders: `./di/bind-production` (real Payload) and `./di/bind-dev-seed` (populated mock). The app's `bindAll()` dispatcher in `apps/web-next/src/server/bind-production.ts` picks one by env: `USE_DEV_SEED="true"` → dev seed; `NODE_ENV="production"` → production; otherwise → dev seed (developer default so `pnpm dev` boots without Payload). Dev seed lives in `src/__seeds__/dev.ts` as a lazy `buildDev<Entities>()` function that uses the feature's existing factory
|
||||
- **Binders take a `ctx` arg from `core-shared/di`** — `bindProductionX(ctx: BindProductionContext)` for production binders; `bindDevSeedX(ctx: BindContext)` for dev-seed. Required fields: `tracer`, `logger`, plus `config` for production. Optional fields: `bus`, `queue`, `realtime`, `realtimeRegistry` (correspond to optional core packages — guard with `?.` or `if (bus) { ... }` when used; use-case signatures should accept the protocol type when they only need protocol methods, not the full concrete interface). Aggregator builds one ctx object and passes it to all feature binders
|
||||
|
||||
Reference in New Issue
Block a user