Home/Product requirements, styled from Markdown
Use cases
Product requirements documents, styled for reviewers who decide
A PRD gets read by people deciding whether to build something. Its requirements table, user stories and acceptance checklist have to be easy to scan as well as easy to write.
Write it flat, let the layout carry the hierarchy
A PRD written in Markdown stays flat: a heading for each section, a bulleted list for goals and non-goals, a table for requirements. Nobody indents by hand or fights a word processor's outline view. The theme turns that flat structure into the visual hierarchy a reviewer expects: heading weight and rule lines do the work manual formatting used to. The document is written once, not reformatted for the meeting where it gets approved.
The non-goals list matters as much as the goals list to a reviewer deciding scope. A plain bulleted list under its own heading keeps the two from blurring together the way a single paragraph of prose can.
Numbered requirement IDs make review traceable
Give each row of the requirements table an ID such as R1, R2, R3 in a csv fence with an ID, Requirement and Priority column. A reviewer can then reference "R4" in a comment instead of quoting the whole requirement. A later revision of the document can add or remove rows without renumbering the ones untouched.
A table also lets a reviewer scan one column at a time in a way a bulleted list does not. Every "Must" priority groups visually even though the rows are not sorted. Every ID is present and accounted for, and no requirement is buried inside a paragraph where it is easy to skim past. That is the difference a PRD needs, since the reader's job is to approve or reject scope, not to read for pleasure.
User stories as numbered items, acceptance criteria as checkboxes
- Write user stories as a numbered list: each one is a discrete scenario a reader can refer to as "story 2" without restating it.
- Write acceptance criteria as a task list, with
- [ ] for an item not yet verified and - [x] for one that is. - The task list renders with real, disabled checkboxes, so a partly verified feature shows which criteria still need testing at a glance.
- Keep one acceptance criterion per line: a line that bundles two conditions cannot be marked half-done.
Worked example
A PRD for a saved-filters feature: a problem statement, goals and non-goals, a requirements table, user stories, an acceptance checklist and open questions.
# Saved Filters for the Support Inbox
## Problem
Agents rebuild the same inbox filters every shift: unassigned tickets over
two hours old, tickets tagged "billing", tickets from a specific customer
tier. There is no way to save a filter and reuse it. Agents either keep a
personal note of the filter steps or re-enter them by hand each time. In a
sample week, agents averaged eleven manual filter rebuilds a day.
## Goals
- Let an agent save the current filter combination with a name.
- Let an agent apply a saved filter from a dropdown in the inbox toolbar.
- Let a team lead share a saved filter with the whole team.
- Reduce manual filter rebuilds by at least half within one quarter.
## Non-goals
- Scheduled or automated filter runs (send a digest, trigger a workflow).
- Filters that combine more than one inbox (this ships for a single inbox).
- A public API for saved filters. Internal use only for this release.
## Requirements
```csv
ID,Requirement,Priority
R1,Save the current filter set with a name up to 40 characters,Must
R2,Show saved filters in a dropdown above the ticket list,Must
R3,Apply a saved filter and update the ticket list within one second,Must
R4,Let the owner rename or delete a saved filter they created,Must
R5,Let a team lead mark a saved filter as shared with the team,Should
R6,Show who created a shared filter and when,Should
R7,Warn before deleting a filter that is shared and in use,Should
R8,Support a maximum of 20 saved filters per agent,Could
```
## User stories
1. As a support agent, I want to save my "unassigned, over two hours"
filter so I can reapply it at the start of every shift without
rebuilding it.
2. As a support agent, I want to see who else uses a shared filter so I
know it is safe to rename without breaking someone else's workflow.
3. As a team lead, I want to publish a filter to the whole team so new
agents start with the same triage view on day one.
## Acceptance criteria
- [x] Saving a filter with no name shows an inline error and does not save.
- [x] A saved filter appears in the dropdown within one page refresh.
- [ ] Applying a saved filter matches the count shown by manual filtering.
- [ ] Renaming a shared filter updates the name for every team member.
- [ ] Deleting a shared filter in use prompts for confirmation first.
- [ ] The 21st saved filter attempt shows the limit instead of saving.
## Open questions
- Should a deleted shared filter leave a placeholder for agents who had it
pinned, or should it disappear from their toolbar immediately.
- Does the 20-filter cap apply per agent per inbox, or per agent across
every inbox they belong to.
- Who approves a shared filter before it reaches the whole team: the team
lead alone, or anyone with edit access to the inbox.
Saved Filters for the Support Inbox
Problem
Agents rebuild the same inbox filters every shift: unassigned tickets over
two hours old, tickets tagged "billing", tickets from a specific customer
tier. There is no way to save a filter and reuse it. Agents either keep a
personal note of the filter steps or re-enter them by hand each time. In a
sample week, agents averaged eleven manual filter rebuilds a day.
Goals
- Let an agent save the current filter combination with a name.
- Let an agent apply a saved filter from a dropdown in the inbox toolbar.
- Let a team lead share a saved filter with the whole team.
- Reduce manual filter rebuilds by at least half within one quarter.
Non-goals
- Scheduled or automated filter runs (send a digest, trigger a workflow).
- Filters that combine more than one inbox (this ships for a single inbox).
- A public API for saved filters. Internal use only for this release.
Requirements
User stories
- As a support agent, I want to save my "unassigned, over two hours"
filter so I can reapply it at the start of every shift without
rebuilding it.
- As a support agent, I want to see who else uses a shared filter so I
know it is safe to rename without breaking someone else's workflow.
- As a team lead, I want to publish a filter to the whole team so new
agents start with the same triage view on day one.
Acceptance criteria
Open questions
- Should a deleted shared filter leave a placeholder for agents who had it
pinned, or should it disappear from their toolbar immediately.
- Does the 20-filter cap apply per agent per inbox, or per agent across
every inbox they belong to.
- Who approves a shared filter before it reaches the whole team: the team
lead alone, or anyone with edit access to the inbox.
Rendered in the Swiss theme. Open it in the editor to change the theme or the text.
Swiss for a decisive read, Slate if the document goes into a wiki
The example above uses Swiss: uppercase headings with letter spacing, hard black rules and a solid black table header, set in heavy-weight Archivo. The look reads as decided rather than open for debate. It suits a spec with numbered sections a team is expected to act on, not one still being drafted.
If the PRD is going to sit inside a product wiki alongside other documents, Slate is the better fit. Plain Inter, cool greys and blue links keep it neutral. A tighter 16px base than the bolder themes lets it sit next to a dozen other pages without standing out.
Two ways to hand it off
For a sign-off meeting, open the document in the editor and use "Print or save as PDF" from the export menu. It opens the browser's print dialog, and choosing "Save as PDF" there gives reviewers a fixed page they can annotate or file alongside the decision.
For a document that lives inside a wiki, use "Copy styled HTML" and paste directly into the page. The styles are inlined, so the requirements table and the acceptance checklist keep their look. List markers on the numbered user stories may not survive every editor. "Download .html" is the alternative when the destination is a file rather than a paste: one page with the theme's styling baked in, fonts and all.
Questions
Why a table for requirements instead of a bulleted list?
A table with ID, Requirement and Priority columns lets a reviewer scan down one column at a time: every "Must" together, every ID accounted for. A bulleted list forces a reviewer to reread each line to find that structure.
Can I circulate the PRD as a PDF for sign-off?
Yes. Open the document in the editor and choose "Print or save as PDF" from the export menu. The browser's print dialog opens next, and saving from there gives reviewers a PDF for sign-off, with the requirements table and checklists printing exactly as they render.
Does pasting this into a wiki keep the table and checkboxes?
"Copy styled HTML" inlines the styles so the table borders and heading weight survive a paste into most wiki and CMS editors. Checkbox marks in the acceptance criteria carry over as disabled checkboxes; list markers on the numbered stories may not.
What if my requirements table has more columns than ID, Requirement and Priority?
The csv fence renders any number of columns from the first row as the header. Add an Owner or Status column and it appears in the table with no other change to the document.