Captures the design from the brainstorm session on agent-first development in this template. Architecture doc covers the four interlocking pillars: - Conformance engine (manifest + brands + ESLint + boot + CI gate) - Agent workflow (PRD -> Epic -> Story -> Task; manifest-first ordering; TDD per slice; in/out scope at every level) - Local task system at docs/work/ (filesystem markdown, derived committed _state.json, single-writer orchestrator rule) - Sandcastle orchestrator (implementer + reviewer loop, DAG-respecting, configurable retry cap) Work-shape guides extend the architecture doc with operational detail for frontend work (atomic design, Storybook-as-spec, component + Playwright screenshot test gates, Storybook MCP reviewer integration) and infrastructure work (ADR-first flow, dedicated ADR elicitation skill, optional core packages vs. new infrastructure layers). Phasing is conformance-first: build the enforcement system manually, then build the dispatch substrate, then migrate remaining features through it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
130 lines
7.0 KiB
Markdown
130 lines
7.0 KiB
Markdown
# Frontend work shape
|
||
|
||
How frontend work — components, pages, media UI, anything visual — flows through the agent-first workflow. For the broader workflow context see [`docs/architecture/agent-first-workflow-and-conformance.md`](../architecture/agent-first-workflow-and-conformance.md).
|
||
|
||
## When this guide applies
|
||
|
||
You're working on:
|
||
|
||
- A new or existing component (atom / molecule / organism / template / page)
|
||
- A page in `apps/web-next` or `apps/web-tanstack`
|
||
- A visual or interactive change in `@repo/core-ui` or `features/<feature>/src/ui/`
|
||
- Storybook stories or visual regression tests
|
||
|
||
If you're working on a backend use case (factory, repository, manifest entry, event handler, job, realtime channel), use the default backend shape documented in the architecture doc — not this guide.
|
||
|
||
## Where frontend code lives
|
||
|
||
| Surface | Location | When to use |
|
||
|---|---|---|
|
||
| Atomic-design primitives | `@repo/core-ui/src/{atoms,molecules,organisms,templates}/` | Cross-feature reusables. Generated via `pnpm turbo gen core-ui-component`. |
|
||
| Feature-scoped UI | `features/<feature>/src/ui/` | Components and queries specific to a feature. Exported behind the feature's `./ui` subpath, never the root barrel (see CLAUDE.md). |
|
||
| Pages | `apps/<app>/src/...` (Next.js: `app/`, TanStack: `routes/`) | Page-level composition. Calls use cases via tRPC controllers; composes components. |
|
||
|
||
## Atomic design conventions
|
||
|
||
Tier rules (enforced by the `atomic-tier-import-direction` ESLint rule):
|
||
|
||
| Tier | May import from | May NOT import from |
|
||
|---|---|---|
|
||
| `atoms` | nothing else in `core-ui` | molecules / organisms / templates / pages / features |
|
||
| `molecules` | atoms | organisms / templates / pages / features |
|
||
| `organisms` | atoms, molecules | templates / pages / features |
|
||
| `templates` | atoms, molecules, organisms | pages / features |
|
||
| `pages` | all of the above | other pages |
|
||
|
||
Feature-scoped UI (`features/<feature>/src/ui/`) follows the same tier order internally, and may import from `@repo/core-ui` at any tier.
|
||
|
||
## Storybook is the spec
|
||
|
||
Every component has a sibling `.stories.tsx`. The story file:
|
||
|
||
- Declares one story per AC bullet (or one variant per AC bullet)
|
||
- Uses Storybook's `play` function for interaction tests where applicable
|
||
- Becomes the shared visual contract between human, implementer agent, reviewer agent
|
||
|
||
**Acceptance criteria for a frontend task map directly to story variants:**
|
||
|
||
```markdown
|
||
## Acceptance criteria
|
||
- [ ] Renders default variant
|
||
- [ ] Renders loading state
|
||
- [ ] Renders error state with `message` slot
|
||
- [ ] Renders disabled state
|
||
- [ ] Click handler fires with event payload
|
||
```
|
||
|
||
Each bullet becomes one `Story` export (or one `play` step on a story).
|
||
|
||
## Test gates
|
||
|
||
| Gate | What it covers | Tool | Latency | When it runs |
|
||
|---|---|---|---|---|
|
||
| Component test | behavior, props, interactions | Vitest + Testing Library, or `play` on stories | <5s | pre-commit, CI |
|
||
| Visual regression | rendered appearance vs. baseline | Playwright screenshot tests | 30–120s | CI only; blocks merge on unapproved diffs |
|
||
|
||
The visual regression infrastructure ships as part of the `work-system-v1` epic. Until it's in place, frontend work relies on component tests + manual visual review.
|
||
|
||
## Adapted four-step ordering
|
||
|
||
For a pure UI slice (no backend coupling):
|
||
|
||
1. **Story file** — write or extend `.stories.tsx`; declare the variant for this slice's AC bullet. *This is the visual spec — analogous to the manifest entry for backend work.*
|
||
2. **Contracts** — props interface in the component file (factory body / render body may still throw `not implemented`)
|
||
3. **Tests (red)** — component test + the new story (the rendered output is asserted as part of the visual regression baseline, or via Testing Library)
|
||
4. **Implementation (green)** — render JSX, wire interactions, satisfy AC
|
||
|
||
For a UI slice that consumes a backend use case (e.g. a form component calling `auth.signUp`), the use case lives in a separate story with its own four steps; the UI story `depends-on` the use-case story.
|
||
|
||
## Reviewer integration
|
||
|
||
The reviewer agent for frontend tasks uses two extra inputs beyond the standard diff:
|
||
|
||
1. **Storybook MCP** at `http://localhost:6006/mcp` — query existing components, list variants, fetch the metadata for stories that already exist. The reviewer can `list-all-documentation` to verify no duplicate component was created.
|
||
2. **Playwright screenshot CI verdict** — the visual diff status from CI. Unapproved diffs trigger `reject` regardless of code quality.
|
||
|
||
Reviewer checklist for frontend tasks:
|
||
|
||
- [ ] Every AC bullet has a matching story or `play` step
|
||
- [ ] No accidental cross-tier imports (lint already catches this, but verify)
|
||
- [ ] Component test exercises each AC bullet
|
||
- [ ] Visual regression diff is either zero or human-approved
|
||
- [ ] No new component created without checking for an existing equivalent via Storybook MCP
|
||
|
||
## Story split for page-level features
|
||
|
||
A user-facing feature like "sign up" decomposes into multiple stories under one epic:
|
||
|
||
```
|
||
Epic: auth-v1
|
||
├── Story (user-story): auth.signUp use case
|
||
├── Story (technical-story): SignUpForm component
|
||
│ depends-on: signUp use case
|
||
└── Story (technical-story): /sign-up page
|
||
depends-on: SignUpForm
|
||
```
|
||
|
||
Each story has its own AC checklist; the `depends-on` edges enforce sequential dispatch by the orchestrator. The page story typically includes the Playwright E2E test for the full flow.
|
||
|
||
## Conformance for frontend
|
||
|
||
New ESLint rules added under the frontend work-shape:
|
||
|
||
- `component-must-have-story` — every `.tsx` file exporting a default OR named React component must have a sibling `.stories.tsx`
|
||
- `component-must-have-test` — every component must have a sibling `.test.tsx` (or be covered by a `play` function on its story)
|
||
- `atomic-tier-import-direction` — tier imports must respect the table above
|
||
- `story-must-cover-all-prop-variants` (advisory) — discriminated-union props should have a story per variant
|
||
|
||
## Common pitfalls
|
||
|
||
- **Stale stories.** A component changes prop shape; stories don't get updated. The `component-must-have-story` rule catches missing stories but not stale ones. Reviewer should flag this; visual regression catches the rendered consequence.
|
||
- **Visual-only changes without story update.** A CSS tweak that doesn't change behavior still needs the story to be re-snapshotted. Treat the visual regression diff approval as part of the slice.
|
||
- **Cross-tier creep.** Tempting to import an organism from inside an atom for "convenience". The lint rule blocks it; refactor the shared bit down to an atom or molecule.
|
||
- **Duplicate components.** An agent creates a `Button` in a feature's `ui/atoms/` when one already exists in `core-ui`. Reviewer queries Storybook MCP for `Button` before approval; if duplicated, rejects.
|
||
|
||
## Open items (filled in as we ship)
|
||
|
||
- Playwright screenshot infrastructure — exact setup, baseline storage, approval flow
|
||
- Visual regression PR check — GitHub workflow + diff hosting
|
||
- Storybook test integration (`test:stories`) — current status and what we extend
|