Skip to main content

Product ↔ R&D Handoff

How a feature travels from idea to shipped code without screenshots, without duplicate components, and without ambiguous handoffs. The guiding principle:

For an agent, the contract is code and tokens β€” not pixels. The @bewith-dev/design-system repo is the single source of truth. Both design production and implementation anchor to it.

This page is the map. The artifacts it produces are described in the PRD template and Design Doc template.

Product-author's side: how a feature is explored and normalized into a PRD before it reaches this pipeline is documented in Product Authoring. This page picks up where that one leaves off.


TL;DR​

StageOwnerArtifactTool
1. Capture intentProductPRD (docs/prds/<slug>-<cu-id>.md)prd-writer agent
2. Design referenceDesignerFigma frame (Dev Mode) OR Claude Design code branchPath A or B (below)
3. Hand offProductPRD status: ready-for-rd/handoff β†’ gatekeeper validates
3b. CTO reviewProduct β†’ CTOCTO-review ticket in the ClickUp "CTO Review" list (tag cto review, full handoff package)/cto-review
4. Translate to designR&DDesign Doc (docs/designs/<slug>-<cu-id>.md) β€” Β§7.2.a deltas become design-system prerequisite tasks/plan-feature
4b. Approve designR&DDesign Doc status: approvedgatekeeper agent validates (Mode B)
5. Break into tasksR&DGitHub Issues, each linked to ClickUp parent/breakdown
6. BuildR&DCodearchitect, Claude Code, design-system catalog
7. VerifyProduct + R&DDoD checked offprocess-guardian agent

The pipeline at a glance​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ @bewith-dev/design-system (source of truth) β”‚
β”‚ tokens (palette.ts) Β· components Β· CLAUDE.md β”‚
β”‚ Β· COMPONENTS.md catalog Β· Storybook β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ anchors to β”‚ anchors to
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Path A β€” Figma (mature) β”‚ β”‚ Path B β€” Claude Design β”‚
β”‚ Dev Mode MCP + Code β”‚ β”‚ (greenfield exploration) β”‚
β”‚ Connect β†’ structured ref β”‚ β”‚ prompt β†’ code branch β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ design reference (code + component refs)
β–Ό
PRD Β§7.2 names components from COMPONENTS.md
PRD Β§7.2.a lists each design-system delta
(reuse Β· variant Β· element Β· component Β· composite)
β”‚
β–Ό
/handoff β†’ ready-for-rd ──▢ /cto-review opens
β”‚ CTO-review ticket (ClickUp)
β–Ό
R&D runs /plan-feature β†’ Design Doc draft
β”œβ”€ Β§7.2.a deltas β†’ design-system tasks (ship FIRST)
└─ consuming-app tasks depend on them
β”‚
β–Ό
/breakdown β†’ GitHub Issues β†’ ClickUp tasks
β”‚
β–Ό
Implementation: Claude Code reads design-system + tokens
β”‚
β–Ό
process-guardian verifies DoD β†’ shipped

Status (2026-06): COMPONENTS.md + the npm run catalog generator ship with design-system PR #326 (in review). Until it merges, the live catalog is Storybook (https://bewith-dev.github.io/design-system/) + src/components. Treat COMPONENTS.md as the target contract.


Roles & responsibilities​

RoleOwnsReadsOutput
ProductPRD content, UI Composition table, Acceptance Criteriadocs/company/ (brand) + COMPONENTS.md (component names)PRD at docs/prds/<slug>-<cu-id>.md; design reference
Designer (often the same person)Design reference (Figma frame or Claude Design output)PRD Β§1-6, COMPONENTS.md, palette.tsFigma frame published for Dev Mode access OR Claude Design code branch
R&D / EngineerDesign Doc, code, testsPRD, design reference, COMPONENTS.md, repo CLAUDE.mdDesign Doc at docs/designs/<slug>-<cu-id>.md; GitHub Issues; shipped code

The boundary between Product and R&D is enforced by the PRD template ("what does NOT belong here") and by the gatekeeper agent reviewing the PRD against the Definition of Ready before hand-off.

Independent human review at each gate (no self-approval)​

A gate is only real if an independent human stands behind it β€” the producer self-assessing its own output is not a gate.

  • Hand-off (PRD): the product owner ratifies the PRD before ready-for-rd. A P0 requirement may not be weakened by an open question the producer resolved on its own β€” that is the product owner's decision, recorded.
  • Design review (DR): the CTO / engineering reviewer approves the Design Doc before approved, with particular attention to the source-of-truth and reuse checks (gatekeeper Mode B, section G).
  • A gate run only by the producer (the agent that authored the artifact) is flagged, not accepted; it must be signed by the independent reviewer above. (POC lesson: gates were self-run, P0 open questions self-resolved, the Design Doc self-"approved" β€” so the data-source and product decisions slipped to build time.)

Product-side note β€” no reject-and-redo loop. When the product author plans once and will not rewrite (their own environment, e.g. the bewith-product-handoff flow), "reject and send back" is not a usable backstop. Alignment must succeed in that single pass β€” the author sees the design-system UI reference and confirms it before hand-off. There the gatekeeper acts as a safety-net / signal (a gap it finds points to a fix in the front-end tooling), not a bounce that asks the author to redo the work.


Lifecycle & statuses​

StatusWhat it meansWho sets it
draftPRD is being written. Not yet hand-off ready.Author
ready-for-rdPRD passes Definition of Ready. R&D can start the Design Doc.Author after Gatekeeper approves
in-progressR&D has started building.R&D lead
shippedAll DoD items checked.R&D + Product
deprecatedFeature removed or replaced.Owner

The same statuses apply to the Design Doc (with in-review and approved between draft and in-progress). The draft β†’ approved transition is gated by gatekeeper in Mode B β€” the same independent readiness check it runs on the PRD, applied to the Design Doc's Β§1-Β§15 (completeness, design soundness, traceability to the PRD, a filled Β§13 Task Breakdown). Β§16 Definition of Done is not part of this gate β€” that is process-guardian's check at closure.


Stage 3b β€” the CTO-review ticket​

When a PRD reaches ready-for-rd, /handoff opens a CTO-review ticket via /cto-review so the CTO sees every feature before R&D commits to building it. The ticket lands in the dedicated ClickUp "CTO Review" list, tagged cto review, and carries the whole handoff package in one place β€” problem/outcome, scope, UI composition (components from COMPONENTS.md), the design reference, acceptance criteria, and links to the PRD + parent task. The review needs no extra digging.

Title convention, so the list scans cleanly:

[Feature name] informative title

The [Feature name] prefix stays regardless; the rest is a one-line plain statement of scope (editable after creation). Example: [WhatsApp OTP] Add WhatsApp as an OTP delivery channel for the consumer app.

The same command runs manually on a task that did not come through the flow β€” a one-off the CTO should still see β€” gathering whatever handoff fields exist and marking the rest as not provided (never invented). It opens the ticket and stops there; the CTO drives the review.


Path A β€” Figma (mature library, existing designs)​

For features that already have Figma designs, turn Figma into something an agent consumes deterministically:

  • Dev Mode MCP server (Figma) lets Claude Code read frames as structured data (layout, tokens, generated code) β€” not screenshots.
  • Code Connect (Figma) maps each Figma component to the real component in @bewith-dev/design-system, so the MCP returns "use <Button variant="primary"> from the library" instead of a generic <div>. This is the lever that kills screenshots and guarantees reuse.

Connecting it (once)​

  1. Dev Mode MCP is declared in @bewith-dev/design-system/.mcp.json. The endpoint is Figma's local Dev Mode server (typically http://127.0.0.1:3845/mcp), which runs inside the Figma desktop app β€” open the file in Figma desktop and enable the Dev Mode MCP server for it to connect.
  2. Code Connect mappings live as *.figma.tsx files next to each component in @bewith-dev/design-system, published with the Code Connect CLI. Each maps a Figma component (by node URL) to the real @bewith-dev/design-system component + props.

Verify current setup on Figma's side β€” Dev Mode MCP and Code Connect are Figma features and their configuration evolves (the endpoint may be /mcp or /sse depending on version).

Path B β€” Claude Design (greenfield, fast exploration)​

When there is no Figma yet, Product describes intent and the output is code. The critical input: give Claude Design this design system's context β€” the tokens and the COMPONENTS.md catalog β€” so the output uses our components instead of inventing them. Because the output is code landing in a repo/branch, Claude Code reads it directly: code-to-code handoff, zero images.

Use Path B for early exploration; once a pattern stabilizes, promote shared pieces into @bewith-dev/design-system (Path A territory) so they are reused, not re-created.


What a good PRD Β§7 looks like​

Instead of attaching a mockup and saying "build this," the UI section:

  • Names components from COMPONENTS.md (e.g. "header uses SummaryCard + Chip; primary action is Button").
  • References tokens for any color/spacing intent (e.g. "use semantic.success"), never raw hex.
  • Links the Figma frame (Path A) and/or the Claude Design branch (Path B).
  • Itemizes every design-system delta in Β§7.2.a: each component the feature touches gets a row with a delta type (reuse / variant / element / component / composite) and the exact design-system command it maps to. This is the structured list /plan-feature turns into tasks, not a prose aside, and nothing is hand-rolled in the consuming app.

This makes the R&D task implementable pixel-perfect on the first pass.


Design-system deltas ship first​

The PRD's Β§7.2.a is the deterministic bridge between "what the UI needs" and "what the shared design system must grow." It lists every component the feature touches, each tagged with a delta type drawn from the catalog's own vocabulary, so each maps 1:1 to a design-system command:

Delta typeWhat it isDesign-system task
reusealready in COMPONENTS.mdnone β€” reference the import path
varianta new prop / state / style on an existing component (never a fork)/add-variant <Component> <desc>
elementa brand-new primitive/add-component <Name> element
componenta brand-new composed / feature-level component/add-component <Name> component
compositea new component assembled only from existing catalog pieces/add-composite <Name> <desc>

/plan-feature reads Β§7.2.a row by row and emits one design-system task per non-reuse row, recording them in the Design Doc's Β§13 Task Breakdown as prerequisites: the /add-variant Β· /add-component Β· /add-composite work runs in @bewith-dev/design-system and ships before the feature is built in organization-dashboard (or whichever consuming app Β§2 names). The consuming-app frontend tasks Depend on the design-system tasks, so the ordering is enforced by the dependency graph, not by a reviewer remembering.

Why this matters: it is the operational form of "the contract is code and tokens, not pixels." A component the feature needs is either in the catalog (reuse) or a tracked change to the shared system (a delta with a command). There is no third path where the app quietly hand-rolls a one-off. gatekeeper enforces it β€” it sends the PRD back unless Β§7.2.a is well-formed and every component named in Β§7.2 is either in COMPONENTS.md or carries a Β§7.2.a row whose command matches its delta type.


The task pipeline (ClickUp ↔ GitHub Issues)​

  1. PRD created β†’ corresponding ClickUp parent task (CU-XXXXX) created. The clickup_parent frontmatter on the PRD links the two.
  2. PRD reaches ready-for-rd β†’ R&D opens the Design Doc.
  3. Design Doc Β§13 Task Breakdown filled β†’ R&D runs /breakdown to convert each task row into a GitHub Issue, each labeled with the parent CU-id.
  4. Every Issue includes the BeWith 6-section format (project_gh_issue_format). Effort and risk labels come from the Task Breakdown row.
  5. PRs reference the Issue + the parent CU-id; process-guardian verifies the full DoD before closure.

Who lives where β€” and when NOT to create an Issue​

The two trackers split by audience, and the mirror between them is conditional, not 1:1:

  • ClickUp = the product board. Product tasks + their sub-tasks β€” the unit PMs/sales/support/management see and report progress on in the daily. (May move to Jira later.)
  • GitHub Issues = the software breakdown R&D does on a product task β€” one Issue per PR-sized chunk, the engineering detail Product doesn't need to see.

Rules (the point is easy tracking + visible progress + no noise, not symmetry):

  • Create a GitHub Issue only when there is real software decomposition. A small ClickUp task that is itself one piece of work needs no Issue β€” work it directly (branch β†’ PR referencing the CU-id). Forcing a 1:1 Issue per ClickUp task is duplication and noise.
  • A task too big to track as one β†’ break it into smaller ClickUp sub-tasks (so the board shows movement and items come off the board), and open GitHub Issues only for the software pieces that compose them.
  • Product-visible building-blocks the team reports on in the daily live in ClickUp (as tasks or sub-tasks), opened by R&D; the engineering detail that doesn't interest Product stays in the Issues.

This is the complexity gate, applied to the whole pipeline: a small change skips PRD + Design Doc and goes straight to a branch/PR (or one Issue); a medium one fills only the relevant Design Doc sections; a feature runs the full chain. Same artifacts at variable depth β€” never a parallel /specs-style model. When an Issue does exist, state-sync keeps the bidirectional ClickUp↔Issue mirror; when one doesn't, ClickUp alone is the record. This system is experimental β€” we optimize it in use.


Enforcement (so the source of truth doesn't leak)​

Two layers:

  1. @bewith-dev/design-system/CLAUDE.md instructs every agent working in any consuming repo to assemble only from the library and tokens.
  2. lint / CI in design-system blocks raw hex and ad-hoc duplicates of catalog components.

If a one-off color or a local copy of a library component slips in β€” stop. That belongs in the design system. Open an /add-component task and consume it from there.


Maintenance checklist (design-system)​

These keep the SoT machine-readable. Maintained in @bewith-dev/design-system:

  • New/changed component β†’ npm run catalog (refresh COMPONENTS.md) (ships with PR #326)
  • New/changed component β†’ add/update its Storybook story
  • New shared color/spacing β†’ add a token in palette.ts, never inline
  • PRD Β§7.2 references catalog component names + tokens, not screenshots
  • PRD Β§7.2.a itemizes every design-system delta with its type + command; non-reuse rows become design-system tasks that ship before the consuming-app build
  • Figma shared components have a Code Connect mapping to the catalog entry

See also​