PM × Engineering

Spec-to-React Template

A PM-to-frontend handoff template that translates product requirements into React component trees, state management, and API integration specs. Cut design-to-code ambiguity in half. Free to copy, download, and use. No signup required.

Template
# Spec-to-React Template

**Feature:** [Feature Name]
**PM:** [Name]
**Frontend Engineer:** [Name]
**Designer:** [Name]
**Date:** [Date]
**Target Sprint:** [Sprint]

---

## 1. Feature Summary

> What does this UI do? Who uses it? What's the success outcome?

[Write here]

---

## 2. Component Tree

> Sketch the component hierarchy. Names should match what you'll name the files.

```
<FeaturePage>
  <PageHeader title="..." />
  <FeatureList>
    <FeatureCard key={id} />
    <FeatureCard key={id} />
  </FeatureList>
  <EmptyState />          ← show when list is empty
  <FeatureModal />        ← show on create/edit
  <DeleteConfirmDialog /> ← show on delete
</FeaturePage>
```

---

## 3. Component Specs

### [ComponentName]

**Purpose:** [One sentence]

**Props:**
| Prop | Type | Required | Default | Notes |
|---|---|---|---|---|
| | string | Yes | — | |
| | boolean | No | false | |

**States:**
| State | Type | Initial Value | Description |
|---|---|---|---|
| isLoading | boolean | false | True while API call in-flight |
| error | string | null | null | API error message |
| items | Item[] | [] | Fetched list data |

**Events / Callbacks:**
| Event | Trigger | Handler |
|---|---|---|
| onClick | User clicks create button | Opens FeatureModal |
| onDelete | User clicks delete | Calls DELETE /api/v1/... |

---

## 4. Page States

Every page has multiple states. Define them all upfront.

| State | Trigger | What the User Sees |
|---|---|---|
| Loading | On mount, before API responds | Skeleton cards |
| Empty | API returns [] | EmptyState component with CTA |
| Populated | API returns items | List of FeatureCard |
| Error | API returns 4xx/5xx | Error banner with retry button |
| Submitting | User clicks Save in modal | Button shows spinner, form disabled |

---

## 5. API Integration

| Hook / Function | Endpoint | Method | Trigger | On Success | On Error |
|---|---|---|---|---|---|
| useFeatures() | /api/v1/features/ | GET | On mount | Set items | Set error |
| createFeature() | /api/v1/features/ | POST | Modal submit | Append to list, close modal | Show toast error |
| deleteFeature(id) | /api/v1/features/{id}/ | DELETE | Confirm dialog | Remove from list | Show toast error |

---

## 6. Routing

| Route | Page Component | Auth Required | Notes |
|---|---|---|---|
| /app/features | FeaturePage | Yes | — |
| /app/features/[id] | FeatureDetailPage | Yes | Redirect to 404 if not found |

---

## 7. Form Validation

| Field | Type | Required | Validation Rules | Error Message |
|---|---|---|---|---|
| name | text | Yes | Min 3 chars, max 100 | "Name must be 3–100 characters" |
| status | select | Yes | One of [active, archived] | "Select a valid status" |

---

## 8. Responsive Behaviour

| Breakpoint | Layout | Notes |
|---|---|---|
| < 768px (mobile) | Single column, no sidebar | FeatureModal becomes full-screen drawer |
| 768–1024px (tablet) | Two-column grid | — |
| > 1024px (desktop) | Three-column grid | — |

---

## 9. Accessibility

- [ ] All interactive elements have `aria-label` or visible label
- [ ] Delete confirmation dialog traps focus
- [ ] Loading state announced with `aria-live="polite"`
- [ ] Color is not the only differentiator (icons + text labels)
- [ ] Keyboard navigation: Tab order is logical; Esc closes modals

---

## 10. Edge Cases

- [ ] What if an item is deleted while it's open in the detail view?
- [ ] What if the create POST takes > 5 seconds?
- [ ] What if the list has > 500 items — do we paginate?
- [ ] What if the user refreshes mid-form?

How to use this Spec-to-React template

1

Draw the component tree first

A quick ASCII component tree (like the one in the template) eliminates most naming and nesting debates. Do this before writing anything else — it takes 10 minutes and saves 3 rounds of Figma-to-code interpretation.

2

Define every page state explicitly

Loading, empty, populated, error, and submitting are the five states every data-driven page has. If you don't specify them, engineers and designers make different assumptions — and users get blank screens with no feedback.

3

List API calls with their side effects

For each API call, specify what happens on success (update state? close modal? show toast?) and what happens on error. 'On success, append to list' is something engineers shouldn't have to guess.

4

Include accessibility requirements before code is written

Retrofitting accessibility onto finished UI is expensive. The checklist in Section 9 takes 5 minutes to review but saves 2 sprints of a11y fixes. Review it with the designer, not just the engineer.

Want a Spec-to-React grounded in your actual customer data?

PMRead ingests your customer interviews, feedback, and Slack threads — and generates PRDs backed by real evidence, not guesses.

Try PMRead free →

Frequently asked questions

Do I need a Spec-to-React template if we already have Figma designs?

Yes. Figma shows what it looks like — this template specifies what it does. State management, API integration, error handling, and edge cases are invisible in Figma. Engineers build from both.

What level of detail should I specify for component props?

Specify props that have business logic implications (e.g., 'isPro: boolean — controls whether the upgrade banner shows'). Skip purely presentational props (e.g., className, style) — those are the engineer's domain.

How is this different from a design handoff in Figma?

Figma communicates visual design. This template communicates behavior, state, data flow, and API contracts. Both are necessary — neither replaces the other.

Should I fill this in for every UI change?

No — for minor copy changes, color tweaks, or single-field form additions, a Jira ticket is sufficient. Use this template for any feature that introduces new components, new routes, or new API calls. A good rule of thumb: if it takes more than 2 days to build, it deserves a spec.