Skip to main content

Generate user story maps from markdown

Project description

storymap

Generate user story maps from markdown. Write your product spec as a readable document — personas, releases, activities, tasks, and stories — and render it as a styled HTML page.

Installation

pip install storymap

Quick start

storymap init                   # create a skeleton storymap.md
storymap init myproduct.md      # create a named skeleton
storymap render mymap.md        # → mymap.html (same directory)
storymap render mymap.md -o out # → out/mymap.html

PDF output: open the generated HTML in a browser and use print-to-PDF (Ctrl+P → Save as PDF). The HTML includes print-optimised CSS for landscape layout and color preservation.

Document format

A storymap file is a standard markdown document with three reserved top-level sections: # Releases, # Personas, and # Map. Any other # heading is treated as the document title (first one) or passed through to the output.

# My Product
Short description.

# Releases
## MVP
First public release.

## Beta
Invite-only beta with selected users.

# Personas
## Margie the Manager
- **Age:** 45–55
- **Tech level:** Low

Margie manages a team of 8 and primarily uses the app on mobile.

# Map
## User Management
### Authentication
#### Sign in [status:: done] [persona:: Margie the Manager]
User can log in with email and password.

> release Beta

#### Password reset [status:: in-progress] [deadline:: 2026-03-01]

### Profile
#### Edit profile [status:: done]

> release Beta

#### Upload avatar [status:: blocked]
Blocked pending storage provider decision.

Sections

Section Required Purpose
# Releases Yes Defines release swimlanes
# Personas No UX persona descriptions
# Map Yes The story map itself

Section names are case-insensitive.

Map hierarchy

## Activity       (column group)
### Task          (column)
#### Story        (card in a swimlane)

Use > release on its own line to advance to the next release swimlane within a task. Annotate it for readability — anything after release is ignored:

### Authentication
#### Sign in          ← Release 1 (MVP)
#### Remember me      ← Release 1 (MVP)
> release Beta
#### SSO              ← Release 2 (Beta)
> release GA
                      ← Release 3 empty for this task

Keep > release count consistent across all tasks — mismatched counts produce misaligned swimlane rows.

Story fields

Stories support optional inline fields using [key:: value] syntax. Fields appear as badges on the rendered story card.

#### Story name [status:: done] [persona:: Margie the Manager] [deadline:: 2026-03-01]
Field Values Default
status not-started, in-progress, done, blocked not-started
persona Any string matching a persona name
deadline ISO date YYYY-MM-DD

Any other [key:: value] field is accepted and rendered as a badge.

Story descriptions

Markdown content following a #### Story heading and before the next heading or > release separator is treated as the story description. Descriptions support standard markdown: bold, italics, links, lists.

CLI reference

Usage: storymap [OPTIONS] COMMAND [ARGS]...

  Generate user story maps from markdown.

Options:
  --version  Show the version and exit.
  --help     Show this message and exit.

Commands:
  init    Create a skeleton storymap markdown file to get started.
  render  Render a story map markdown INPUT_FILE to HTML.

storymap render

Usage: storymap render [OPTIONS] INPUT_FILE

Options:
  -o, --output DIR                Output directory. Defaults to the input
                                  file's directory.
  -t, --template FILE             Path to a custom Jinja2 template (.html.j2).
  --status-colors KEY=COLOR,...   Override status colors.
                                  Example: done=#00FF00,blocked=#FF0000
  --ui-colors KEY=COLOR,...       Override UI colors.
                                  Example: activity=#1565C0,task=#90CAF9
  --help                          Show this message and exit.

storymap init

Usage: storymap init [OUTPUT_FILE]

  OUTPUT_FILE defaults to storymap.md in the current directory.
  Refuses to overwrite an existing file.

Customisation

Color overrides

storymap render mymap.md \
  --status-colors "done=#27AE60,in-progress=#2980B9,blocked=#E74C3C" \
  --ui-colors "activity=#2C3E50,task=#34495E"

Default status colors:

Status Color
not-started #E0E0E0 grey
in-progress #90CAF9 blue
done #A5D6A7 green
blocked #EF9A9A red

Custom templates

storymap render mymap.md --template my-template.html.j2

The template receives:

Variable Type Description
document StorymapDocument The full parsed document
status_colors dict[str, str] Resolved status → hex color
ui_colors dict[str, str] Resolved UI element → hex color
render_md callable Render a markdown string to HTML

The darken filter is also available: {{ color | darken }}.

Development

Requires pipenv and just.

git clone https://github.com/mozaicworks/storymap
cd storymap
just install
just test

Project structure

storymap/
├── model.py       — dataclasses and default color constants
├── parser.py      — markdown-it-py state machine parser
├── renderer.py    — Jinja2 HTML renderer
├── cli.py         — click CLI entry point
└── templates/
    └── default.html.j2
tests/
├── test_model.py
├── test_parser.py
├── test_renderer.py
└── test_cli.py

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

storymap-0.1.1.tar.gz (22.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

storymap-0.1.1-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file storymap-0.1.1.tar.gz.

File metadata

  • Download URL: storymap-0.1.1.tar.gz
  • Upload date:
  • Size: 22.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for storymap-0.1.1.tar.gz
Algorithm Hash digest
SHA256 4648984deef8210b0cb4b88aafd0a16a4df325d020c53075eba67219fe356521
MD5 77769cdff31e9a56cf254b9dc5ad5248
BLAKE2b-256 974c1a1e4b077944dd2d79f17504132e9b040f3e6aa892cdde4d6444b95b3611

See more details on using hashes here.

File details

Details for the file storymap-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: storymap-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for storymap-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 efeed37e4950507b81d0421cb346b21e0de64edabef67fd41345ef85b385101a
MD5 a8416e802edd7cef4cc6634f40347ae3
BLAKE2b-256 1a313a47ab034e974a3704d4dee46ed5f48c54df8119e84a738c2c40ffef420e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page