Files
agentic-dev/docs/guides/frontend-work-shape.md
Danijel Martinek f77e6ea881 chore(template): clean-slate template snapshot from bb4a0c7
Curated, product-agnostic snapshot of the post-story-04 tree: demo
content deleted, auth-only reference feature, web-next shell, all gates
green. Product-specific docs, ADRs 027-029, PRDs/epics/archive, editor
library traces, and product naming are curated out; generic template
repairs (coverage provider devDeps, root test:coverage script, live
lint fixes, root-only release-please) are kept. See TEMPLATE.md for
provenance, curation list, and usage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 20:40:54 +02:00

8.1 KiB
Raw Blame History

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.

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:

## 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 30120s 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