22
33Generate user story maps from markdown. Write your product spec as a readable
44document — personas, releases, activities, tasks, and stories — and render it
5- as a styled HTML page or PDF .
5+ as a styled HTML page.
66
77## Installation
88
9- Requires [ pipenv] ( https://pipenv.pypa.io ) and [ just] ( https://github.com/casey/just ) .
10-
119``` bash
12- git clone https://github.com/yourorg/storymap
13- cd storymap
14- just install
10+ pip install storymap
1511```
1612
1713## Quick start
1814
1915``` bash
20- storymap init # → storymap.md in current directory
21- storymap init myproduct.md # → myproduct.md
22- just run mymap.md # → out/mymap.html
23- just run-out mymap.md ./output # → output/mymap.html
24- ```
25-
26- Or directly via pipenv:
27-
28- ``` bash
29- pipenv run storymap render mymap.md --output ./out
16+ storymap init # create a skeleton storymap.md
17+ storymap init myproduct.md # create a named skeleton
18+ storymap render mymap.md # → mymap.html (same directory)
19+ storymap render mymap.md -o out # → out/mymap.html
3020```
3121
3222** PDF output:** open the generated HTML in a browser and use print-to-PDF
33- (Ctrl+P → Save as PDF). Browser print produces better results than any
34- automated converter for wide table layouts.
35-
36- ## Just commands
37-
38- | Command | Description |
39- | ---| ---|
40- | ` just install ` | Install dependencies and package in editable mode |
41- | ` just init ` | Create a skeleton storymap.md in current directory |
42- | ` just init-named FILE ` | Create a skeleton with a specific filename |
43- | ` just run FILE ` | Render HTML output from a markdown file (→ out/) |
44- | ` just run-out FILE DIR ` | Render HTML output to a specific directory |
45- | ` just test ` | Run all tests |
46- | ` just test-v ` | Run all tests with verbose output |
47- | ` just test-module MODULE ` | Run tests for one module (e.g. ` just test-module parser ` ) |
48- | ` just template-path ` | Print the path to the bundled default template |
49- | ` just clean ` | Remove the out/ folder |
50- | ` just clean-build ` | Remove build artifacts including egg-info |
51- | ` just clean-env ` | Remove the virtualenv and lock file |
52- | ` just build ` | Build distribution packages (sdist + wheel) |
53- | ` just publish ` | Upload to PyPI |
54- | ` just publish-test ` | Upload to TestPyPI for a dry run |
55- | ` just release ` | Tag, push, and create a GitHub release |
23+ (Ctrl+P → Save as PDF). The HTML includes print-optimised CSS for landscape
24+ layout and color preservation.
5625
5726## Document format
5827
59- A storymap file is a standard markdown document with four reserved top-level
60- sections: ` Releases ` , ` Personas ` , ` Map ` , and optionally any other headings
61- you want (they are ignored by the renderer but appear in the HTML output) .
28+ A storymap file is a standard markdown document with three reserved top-level
29+ sections: ` # Releases` , ` # Personas` , and ` # Map` . Any other ` # ` heading is
30+ treated as the document title (first one) or passed through to the output.
6231
6332``` markdown
33+ # My Product
34+ Short description.
35+
6436# Releases
6537## MVP
66- First public release targeting core authentication .
38+ First public release.
6739
6840## Beta
6941Invite-only beta with selected users.
7042
7143# Personas
7244## Margie the Manager
7345- ** Age:** 45–55
74- - ** Location:** Suburban midwest
75- - ** Job title:** Operations Manager
76- - ** Tech level:** Low — uses email and Excel, avoids new tools
77-
78- Margie manages a team of 8 and primarily accesses the app on her phone.
79-
80- ![ Margie] ( margie.jpg ) {width=200px}
46+ - ** Tech level:** Low
8147
82- [ Research interview notes] ( https://docs.google.com/... )
83-
84- ## Dave the Developer
85- - ** Age:** 28–35
86- - ** Tech level:** High — API-first mindset
48+ Margie manages a team of 8 and primarily uses the app on mobile.
8749
8850# Map
8951## User Management
9052### Authentication
9153#### Sign in [ status:: done] [ persona:: Margie the Manager]
9254User can log in with email and password.
93- See [ issue #1 ] ( https://github.com/org/repo/issues/1 )
9455
9556> release Beta
9657
@@ -103,14 +64,6 @@ See [issue #1](https://github.com/org/repo/issues/1)
10364
10465#### Upload avatar [ status:: blocked]
10566Blocked pending storage provider decision.
106-
107- ## Reporting
108- ### Dashboard
109- #### View summary [ status:: not-started] [ persona:: Margie the Manager]
110-
111- > release Beta
112-
113- #### Export to CSV [ deadline:: 2026-06-01]
11467```
11568
11669### Sections
@@ -121,9 +74,7 @@ Blocked pending storage provider decision.
12174| ` # Personas ` | No | UX persona descriptions |
12275| ` # Map ` | Yes | The story map itself |
12376
124- Section names are case-insensitive. Any other ` # ` headings are passed through
125- to the rendered output unchanged, allowing you to add an introduction,
126- project goals, or other context that makes the PDF self-contained.
77+ Section names are case-insensitive.
12778
12879### Map hierarchy
12980
@@ -133,11 +84,8 @@ project goals, or other context that makes the PDF self-contained.
13384#### Story (card in a swimlane)
13485```
13586
136- Stories are grouped into release swimlanes by ` > release ` separators within each
137- task. Stories before the first ` > release ` belong to the first release, after the
138- first ` > release ` to the second release, and so on.
139-
140- You can annotate the separator for readability — anything after ` release ` is ignored:
87+ Use ` > release ` on its own line to advance to the next release swimlane within
88+ a task. Annotate it for readability — anything after ` release ` is ignored:
14189
14290``` markdown
14391### Authentication
@@ -149,11 +97,13 @@ You can annotate the separator for readability — anything after `release` is i
14997 ← Release 3 empty for this task
15098```
15199
100+ Keep ` > release ` count consistent across all tasks — mismatched counts produce
101+ misaligned swimlane rows.
102+
152103### Story fields
153104
154- Stories support optional inline fields using the
155- [ Dataview] ( https://blacksmithgu.github.io/obsidian-dataview/ ) ` [key:: value] `
156- syntax. Fields appear as badges on the rendered story card.
105+ Stories support optional inline fields using ` [key:: value] ` syntax.
106+ Fields appear as badges on the rendered story card.
157107
158108``` markdown
159109#### Story name [ status:: done] [ persona:: Margie the Manager] [ deadline:: 2026-03-01]
@@ -165,21 +115,14 @@ syntax. Fields appear as badges on the rendered story card.
165115| ` persona ` | Any string matching a persona name | — |
166116| ` deadline ` | ISO date ` YYYY-MM-DD ` | — |
167117
168- Any other ` [key:: value] ` field is accepted and rendered as a badge, making
169- the format forward-compatible with future additions.
118+ Any other ` [key:: value] ` field is accepted and rendered as a badge.
170119
171120### Story descriptions
172121
173- Markdown content following a ` #### Story ` heading and before the next
174- heading or ` > release ` separator is treated as the story description. Descriptions
122+ Markdown content following a ` #### Story ` heading and before the next heading
123+ or ` > release ` separator is treated as the story description. Descriptions
175124support standard markdown: bold, italics, links, lists.
176125
177- ``` markdown
178- #### Sign in [ status:: done]
179- User can log in with email and password.
180- See [ issue #1 ] ( https://github.com/org/repo/issues/1 )
181- ```
182-
183126## CLI reference
184127
185128```
@@ -225,10 +168,8 @@ Usage: storymap init [OUTPUT_FILE]
225168
226169### Color overrides
227170
228- Override any status or UI color from the command line:
229-
230171``` bash
231- storymap mymap.md \
172+ storymap render mymap.md \
232173 --status-colors " done=#27AE60,in-progress=#2980B9,blocked=#E74C3C" \
233174 --ui-colors " activity=#2C3E50,task=#34495E"
234175```
@@ -244,21 +185,11 @@ Default status colors:
244185
245186### Custom templates
246187
247- Copy the bundled template and modify it:
248-
249188``` bash
250- # find the bundled template
251- just template-path
252- # → /path/to/storymap/templates/default.html.j2
189+ storymap render mymap.md --template my-template.html.j2
253190```
254191
255- Then render with your custom template:
256-
257- ``` bash
258- storymap mymap.md --template my-template.html.j2
259- ```
260-
261- The template receives the following context variables:
192+ The template receives:
262193
263194| Variable | Type | Description |
264195| ---| ---| ---|
@@ -269,14 +200,12 @@ The template receives the following context variables:
269200
270201The ` darken ` filter is also available: ` {{ color | darken }} ` .
271202
272- ## Known limitations
273-
274- There are no known format limitations at this time.
275-
276203## Development
277204
205+ Requires [ pipenv] ( https://pipenv.pypa.io ) and [ just] ( https://github.com/casey/just ) .
206+
278207``` bash
279- git clone https://github.com/yourorg /storymap
208+ git clone https://github.com/mozaicworks /storymap
280209cd storymap
281210just install
282211just test
0 commit comments