User Stories
Core Format
As a [persona],
I want to [action/capability],
So that [benefit/outcome].
Good vs Bad Examples
BAD: As a user, I want a dashboard so that I can see things.
GOOD: As a marketing manager, I want to see campaign ROI by channel,
so that I can reallocate budget to the highest-performing channels.
BAD: As an admin, I want to manage users.
GOOD: As an account admin, I want to invite team members by email with role assignment,
so that I can control who has access to which features without IT involvement.
Persona Types
- Use specific personas, not "user" (admin, developer, end-user, free user, enterprise customer)
- Personas should reflect real segments in your user research
- Different personas can have conflicting stories — make them explicit
Acceptance Criteria
INVEST Criteria (good story checklist)
- Independent: Can be built without other stories (mostly)
- Negotiable: Implementation details are open
- Valuable: Delivers value to user or business
- Estimable: Team can size it
- Small: Completable in one sprint
- Testable: Acceptance criteria are verifiable
Writing Acceptance Criteria
Format 1: Given/When/Then
Story: As a buyer, I want to filter products by price range
so that I can find items within my budget.
AC-1:
GIVEN I am on the product listing page
WHEN I set a price range of $10–$50
THEN only products priced between $10 and $50 are displayed
AND the count shows the number of filtered results
AC-2:
GIVEN I set min price > max price
WHEN I try to apply the filter
THEN I see an inline error "Min price must be less than max price"
AND the filter is not applied
AC-3:
GIVEN no products match the price range
WHEN filter is applied
THEN empty state is shown with "No products found. Try a wider range."
Format 2: Checklist
Story: As a user, I want to export my data as CSV
Acceptance Criteria:
- [ ] Export button visible to all users with data
- [ ] Clicking export triggers download within 3 seconds for < 10k rows
- [ ] File is named: [feature]-export-YYYY-MM-DD.csv
- [ ] Headers match column labels in the UI
- [ ] Unicode characters are encoded correctly (UTF-8 BOM)
- [ ] For > 10k rows, email download link within 5 minutes
- [ ] Email includes expiry note: link valid 24 hours
- [ ] Export is logged in audit trail
Story Splitting Techniques (SPIDR)
S — Spikes
Split research/technical uncertainty from implementation:
Spike: Investigate OAuth2 providers for social login (2 days → recommendation)
Story: Implement Google OAuth2 sign-in (after spike)
Story: Implement GitHub OAuth2 sign-in (after spike)
P — Paths (Workflow Variations)
Split by user path:
Original: As a user, I want to sign in
Split:
Story 1: Sign in with email/password
Story 2: Sign in with Google SSO
Story 3: Sign in with magic link
Story 4: Sign in on mobile (biometric)
I — Interfaces
Split by platform/channel:
Original: Users can receive notifications
Split:
Story 1: In-app notifications (bell icon)
Story 2: Email notifications
Story 3: Slack notifications
Story 4: Mobile push notifications
D — Data
Split by data complexity:
Original: Support all payment methods
Split:
Story 1: Credit card (Stripe)
Story 2: PayPal
Story 3: ACH / bank transfer
Story 4: International wire transfer
R — Rules (Business Logic)
Split by business rule:
Original: Calculate pricing
Split:
Story 1: Standard pricing (no discounts)
Story 2: Volume discounts
Story 3: Coupon/promo code application
Story 4: Enterprise contract pricing
Story Mapping
Layout
User Activities (top row — goals)
│
├── Discover product
│ ├── See homepage (step)
│ ├── Read blog post (step)
│ └── Watch demo video (step)
│
├── Sign up
│ ├── Fill signup form (step)
│ ├── Verify email (step)
│ └── Complete profile (step)
│
└── First success
├── Create first item (step)
├── Invite teammate (step)
└── See first insight (step)
Release 1 (MVP — must have)
═══════════════════════════════
[Card] [Card] [Card]
Release 2 (better UX)
═══════════════════════════════
[Card] [Card]
Release 3 (polish)
═══════════════════════════════
[Card]
Epic Decomposition
Epic Template
Epic: [Outcome-oriented title]
Goal: [Metric we're moving and by how much]
Why Now: [Strategic reason for prioritization]
Stories:
1. [Story 1] — [Size] — [Sprint target]
2. [Story 2] — [Size] — [Sprint target]
3. [Story 3] — [Size] — [Sprint target]
Definition of Done (Epic):
- [ ] All stories shipped to 100% of users
- [ ] Target metric achieved
- [ ] Docs updated
- [ ] Support trained
Epic Size Guidelines
| T-Shirt | Story Points | Sprint Duration |
|---|---|---|
| XS | 1-3 | < 1 sprint |
| S | 3-8 | 1 sprint |
| M | 8-20 | 1-2 sprints |
| L | 20-40 | 2-3 sprints |
| XL | 40+ | Split into sub-epics |
Story Point Estimation (Planning Poker)
Fibonacci Scale Reference
1: Trivial — copy change, tooltip update
2: Very small — simple UI element, config change
3: Small — single form field with validation
5: Medium — new page with standard CRUD
8: Complex — integration with external API
13: Large — multi-step flow with state management
21: Very large — split this story
Relative Estimation Rules
- Estimate complexity, not time
- Compare to a known reference story
- Account for testing and code review
- When estimates diverge by >2x, discuss before revoting
Story Definition of Done
- Code reviewed and merged
- Unit tests written (coverage maintained)
- Acceptance criteria verified in staging
- No regressions in related areas
- Feature flag configured (if applicable)
- Analytics events firing correctly
- Copy reviewed (no placeholder text)
- Accessibility checked (keyboard nav, screen reader)
- Performance: no LCP/CLS regressions
- Product owner signed off in staging