User Story Template
As a, I want, so that. Ron Jeffries' three Cs. Why the so that clause is the part that survives a refactor of the template, and how to write it in plain prose without losing the discipline.
Weekly digest emails
Active users see what they missed in a weekly digest
Filling the Connextra fields with 'a user wants weekly emails so they get weekly emails' is process theater. The clauses are present but they answer none of the three questions. The team will rediscover what success looks like in review and probably get it wrong.
The three Connextra clauses force the answers to who, what, and why before the story enters a sprint. The tradeoff space is now visible: the audience is low-frequency users, the value is reducing the cost of staying informed.
Customer downloads invoice PDF
Customer downloads invoice PDF
Without 'so that', the team builds 'a PDF download'. Whether the timestamps match the audit, whether 'support escalation rate' goes down, whether this is even the right format, all evaporate. The work ships. The cost stays.
The 'so that' is the part that survives a refactor of the template. It anchors the work to a real cost the customer is paying, which makes it possible to argue scope down or up against the actual goal.
User can see calendar events
Volunteer coordinators see all upcoming shifts at a glance
'A user' is a wildcard that lets the team build for whoever shows up loudest in review. The Connextra template is a forcing function for specificity, and 'user' opts out of the function entirely.
Naming the actor as a volunteer coordinator running a weekend event makes the tradeoffs concrete. Should we sort by time or by gap? Should we send a notification? You cannot answer those for 'a user'.
Build new checkout flow
Returning customers check out in fewer than four screens
AC that point at a Notion doc collapse Confirmation into 'go read the doc'. The doc may be excellent, but the ticket is useless to anyone scanning the board, and the doc rots at a different cadence than the work.
Card: the title and Connextra clauses fit on a card. Conversation: the framing sets up the team to talk through edge cases. Confirmation: the acceptance criteria are observable on the ticket. All three Cs in the ticket itself.
Inventory page filters
Add filters to the inventory page. Filter by status, location, and SKU prefix. Persist the filters in the URL.
Inventory managers come back to a saved view
Inventory managers run the same filter many times a day. Right now the filter resets on every page load, so they re-apply it for every check. They want filters to persist across visits, ideally in the URL so they can bookmark or share with the warehouse team.
A bulleted feature list is not a story even if it lists every requirement. It tells the team what to build. It does not tell them why, or for whom, or what to drop if the sprint runs hot.
Plain prose is fine. The three Connextra questions are all answered: inventory managers (who), filters that persist across visits (what), so they stop re-applying the same filter all day (why). The template is a forcing function, not a syntactic requirement.
As an unspecified user, I want database secrets to be rotated, so that they are rotated.
Rotate the production database secrets
Quarterly rotation, scheduled. Coordinate the cutover with the on-call.
Wrapping plumbing work in a fake 'as a user' clause is process theater. It violates Bill Wake's V (Valuable to a user) and adds noise. The honest move is to call it a Task.
Secret rotation is real work with no user-facing change, so it gets a Task. Trying to force a Connextra clause around it produces tautology. The template is a sanity check for stories, not a costume that every work item has to wear.