Skip to main content

Write books in Markdown, compile to EPUB 3.3 โ€” and deconstruct existing EPUBs back to readable Markdown (best-effort). Like Fountain for screenplays.

Project description

ProseDown

Write books in Markdown. Compile to EPUB. Like Fountain is for screenplays, ProseDown is for ebooks: plain text that compiles to a complex format. Two lines of frontmatter, one Markdown file, valid EPUB 3.3.

CI PyPI Python License: MIT EPUB 3.3

๐ŸŒ jeffalldridge.github.io/prosedown โ€” live site, full spec, cheat sheet.

By Tent Studios, LLC.


Why this exists

Most ebook tools fall into one of three buckets โ€” and each forces a tradeoff most authors don't want to make:

  • Closed editors (Vellum, Scrivener) hide everything in a closed app. You can't open your manuscript anywhere else without exporting.
  • Power tools (Pandoc, LaTeX) are heavy. Full citation engines and custom syntax for things 99% of authors don't need.
  • Raw editors (Sigil, Calibre) make you hand-edit XHTML inside a zip file. Useful for fixing existing books, painful for writing new ones.
Vellum Scrivener Pandoc LaTeX ProseDown
Plain text source โŒ โŒ โœ… โœ… โœ…
Open in any editor โŒ โŒ โœ… โœ… โœ…
EPUB output โœ… โœ… โœ… with effort โœ…
Zero configuration โœ… โŒ โŒ โŒ โœ…
Standard Markdown n/a n/a mostly โŒ โœ…
Free $250 once $59 once โœ… โœ… โœ…
macOS / Win / Linux macOS only โœ… โœ… โœ… โœ…
EPUB โ†’ source โŒ โŒ partial โŒ โœ… (best-effort)

ProseDown sits between: plain Markdown source files an author can open in any editor โ€” Obsidian, VS Code, iA Writer, TextEdit โ€” that compile to a professional EPUB by convention, with no configuration.

ProseDown is not for fixed-layout books, picture books, comics, poetry with line-level control, drama formatting, academic citations, or media overlays. See the scope boundaries in the spec.


Five design principles

The decisions that shape every part of the format.

  1. One file is enough. A single .md with two YAML lines is a valid project. The barrier to entry is zero.
  2. Convention over configuration. Cover auto-detected. CSS auto-detected. Chapter order from filenames. Authors shouldn't configure what can be inferred.
  3. Standard everything. CommonMark Markdown. Standard YAML. No custom syntax. Lock-in is the enemy of adoption โ€” and your files should outlive any single tool.
  4. Two directions. Build is primary, deterministic, EPUBCheck-clean. Deconstruct is best-effort and practical, not a lossless archive.
  5. Non-destructive. Opens cleanly in Obsidian, Hugo, Jekyll, or any other Markdown tool. A format that fights your other tools isn't a format worth adopting.

The whole tool, in seven lines

No configuration files, no project initializer, no template wizard.

cat > on-simplicity.md <<'EOF'
---
title: "On Simplicity"
author: "Jane Smith"
---

# On Simplicity

The simplest things are often the most profound.
EOF

prosedown build on-simplicity.md on-simplicity.epub

That's a valid EPUB 3.3 โ€” passes EPUBCheck, opens in Apple Books, Kobo, Calibre, anything that reads ebooks. Two required frontmatter fields, one Markdown file, no configuration.

When your book outgrows a single file, point prosedown build at a folder of numbered chapters. See spec/examples/ for four progressively larger projects.


How build works

Markdown source on the left, EPUB 3.3 on the right, a small handful of well-defined steps in the middle.

       your project           prosedown build              EPUB 3.3
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚ book.md          โ”‚     โ”‚ parse YAML       โ”‚     โ”‚ META-INF/        โ”‚
   โ”‚ 01-intro.md      โ”‚ โ”€โ”€โ–ถ โ”‚ resolve files    โ”‚ โ”€โ”€โ–ถ โ”‚   container.xml  โ”‚
   โ”‚ 02-chapter.md    โ”‚     โ”‚ render Markdown  โ”‚     โ”‚ OEBPS/           โ”‚
   โ”‚ cover.jpg        โ”‚     โ”‚ build OPF/NCX    โ”‚     โ”‚   chapters/      โ”‚
   โ”‚ style.css        โ”‚     โ”‚ pack ZIP         โ”‚     โ”‚   images/        โ”‚
   โ”‚                  โ”‚     โ”‚                  โ”‚     โ”‚   nav.xhtml      โ”‚
   โ”‚                  โ”‚     โ”‚                  โ”‚     โ”‚   content.opf    โ”‚
   โ”‚                  โ”‚     โ”‚                  โ”‚     โ”‚ mimetype         โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            deterministic ยท EPUBCheck-clean
                            same source โ†’ same bytes

Everything is auto-detected: cover by filename, CSS by filename, chapter order by numeric prefix. Same source produces the same bytes โ€” diff-clean under git, reproducible builds work.


How deconstruct works (the other direction)

An existing EPUB on the left, a clean Markdown project you'd actually want to edit on the right.

      existing.epub             deconstruct            Markdown project
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚ .epub (zip)      โ”‚     โ”‚ read OPF         โ”‚     โ”‚ book.md          โ”‚
   โ”‚   XHTML          โ”‚ โ”€โ”€โ–ถ โ”‚ classify roles   โ”‚ โ”€โ”€โ–ถ โ”‚ 000-cover.md     โ”‚
   โ”‚   + assets       โ”‚     โ”‚ walk spine       โ”‚     โ”‚ 001-chapter.md   โ”‚
   โ”‚   + OPF          โ”‚     โ”‚ XHTML โ†’ Markdown โ”‚     โ”‚ 002-chapter.md   โ”‚
   โ”‚                  โ”‚     โ”‚ extract images   โ”‚     โ”‚ ...              โ”‚
   โ”‚                  โ”‚     โ”‚ extract css      โ”‚     โ”‚ images/          โ”‚
   โ”‚                  โ”‚     โ”‚                  โ”‚     โ”‚ css/             โ”‚
   โ”‚                  โ”‚     โ”‚                  โ”‚     โ”‚                  โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            best-effort ยท documented normalization

Building is the primary use case โ€” stable and deterministic. Deconstruction is best-effort with documented normalization. The goal is readable Markdown an author would want to edit, not a lossless archive of the original EPUB.


ProseDown at a glance

If you only read one section, read this one. The full spec is the source of truth; this is the cheat sheet.

Required frontmatter

Two fields. That's the floor. Everything else is inferred or optional.

---
title: "Your Book"
author: "You"
---

Optional frontmatter

language: en           # default: en
publisher: "โ€ฆ"
date: 2026-04-30
isbn: "978-โ€ฆ"
description: |
  Short blurb.
cover: "cover.jpg"
css: "style.css"

ProseDown synthesizes a deterministic UUID from title + author + language.

Project layouts

# Single-file project โ€” one file, one essay, one EPUB.
my-essay.md     # frontmatter + body

# Multi-chapter project โ€” filename order = chapter order.
my-book/
  book.md          # frontmatter only
  00-copyright.md
  01-chapter-1.md
  02-chapter-2.md
  cover.jpg        # auto-detected
  style.css        # auto-detected

Conventional slugs (auto-classified by role)

  • Frontmatter: copyright, dedication, acknowledgments, foreword, preface
  • Part dividers: part-1, part-2, โ€ฆ
  • Backmatter: afterword, about-the-author, colophon, notes
  • Anything else: chapter

Title resolution

  1. Frontmatter title: (if set)
  2. First # heading in body
  3. Deslugified filename

Same logic on deconstruct โ€” round-trips preserve the title source.

Standard Markdown

CommonMark plus GitHub-flavored extensions: tables, definition lists, fenced code, footnotes ([^1]). No custom dialect.

Excluded files

Filenames starting with _ are skipped at build time. Useful for parking drafts in the same folder.

_09-deleted-scene.md
_draft.md

Pick your path

Three ways into ProseDown depending on what you're trying to do.

1. I want to write a book

You're an author. You want to focus on the words and have something publishable come out the other end.

2. I want to understand the format

You're evaluating ProseDown for a workflow, a tool you're building, or out of curiosity about how the design hangs together.

3. I want to build on it

You're writing a tool, plugin, or alternate compiler. The spec is open and the reference compiler is MIT.


Install

pip install prosedown

Requires Python 3.10+.

prosedown --help
prosedown --version
prosedown build  path/to/project   path/to/output.epub
prosedown deconstruct  path/to/book.epub  path/to/output-project/

The build path uses only MIT- and BSD-licensed dependencies. The deconstruct path additionally pulls in html2text (GPL-3.0+) and EbookLib (AGPL-3.0+) โ€” see THIRD_PARTY_LICENSES.md.


Develop

git clone https://github.com/jeffalldridge/prosedown
cd prosedown
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

prosedown --help
python tests/test_suite.py   # 36 synthetic tests, all green

Running against a real-world corpus

The synthetic tests in tests/test_suite.py always run. To additionally exercise ProseDown against real EPUBs from Standard Ebooks, Project Gutenberg, etc., point at a local corpus:

PROSEDOWN_CORPUS=/path/to/corpus python tests/test_suite.py

The corpus is not redistributed via this repo โ€” it can include copyrighted material. The expected layout is documented in the test file.


What's in this repo

prosedown/
  spec/
    prosedown.md              # โ† The specification (start here)
    xhtml-mapping.md          # Markdown โ†’ XHTML mapping reference
    examples/
      single-file/            # One-file essay
      multi-chapter/          # Numbered chapters in a folder
      multi-part/             # Parts + front/back matter
      with-features/          # Images, captions, glossary

  src/prosedown/              # Reference compiler (Python 3.10+)
    __init__.py
    data/prosedown-default.css

  tests/
    test_suite.py             # 36 synthetic tests, all green

  docs/
    site/                     # GitHub Pages site source
    quickstart.md
    why-prosedown.md

  scripts/
    build_site.py             # Renders spec/prosedown.md โ†’ site

  pyproject.toml              # Installable as `pip install prosedown`

Spec

The current spec is at spec/prosedown.md, version 0.6.1. Pre-1.0; minor refinements likely before 1.0. The spec uses MUST, SHOULD, and MAY per RFC 2119 where two compilers need to agree on exact behavior.

A conforming compiler MUST produce EPUB 3.3 output that passes EPUBCheck without errors.

Implementations in other languages are welcome โ€” see spec/xhtml-mapping.md for the Markdown โ†’ XHTML mapping reference. The full spec also lives as a rendered HTML page at jeffalldridge.github.io/prosedown/spec/.


Roadmap

See ROADMAP.md for what's planned for v0.7, v1.0, and beyond โ€” plus what's deliberately out of scope.

Contributing

PRs welcome โ€” see CONTRIBUTING.md for the setup, PR checklist, and the difference between spec changes and code changes.

For security issues, see SECURITY.md.


Credits

Full attribution in THIRD_PARTY_LICENSES.md.


License

MIT. ยฉ 2026 Jeff Alldridge / Tent Studios, LLC.

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

prosedown-0.6.1.tar.gz (55.1 kB view details)

Uploaded Source

Built Distribution

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

prosedown-0.6.1-py3-none-any.whl (41.7 kB view details)

Uploaded Python 3

File details

Details for the file prosedown-0.6.1.tar.gz.

File metadata

  • Download URL: prosedown-0.6.1.tar.gz
  • Upload date:
  • Size: 55.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for prosedown-0.6.1.tar.gz
Algorithm Hash digest
SHA256 3146ed4710ae61f5ec8a40bc9f934f69d89f493f0f881f804ee41f2f4eec33b3
MD5 d2b221b0318c66178907bd4f0b0742cc
BLAKE2b-256 e87c321acea59488925057fe7110e8597adfb893bc40e985af5c6e3013be604d

See more details on using hashes here.

Provenance

The following attestation bundles were made for prosedown-0.6.1.tar.gz:

Publisher: release.yml on jeffalldridge/prosedown

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file prosedown-0.6.1-py3-none-any.whl.

File metadata

  • Download URL: prosedown-0.6.1-py3-none-any.whl
  • Upload date:
  • Size: 41.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for prosedown-0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9d841155f3e549ad059197e7e84fb01af178880cc868e3c4cd93c22260a082e1
MD5 80778121d2fdae1037869ca44f068d71
BLAKE2b-256 da80e5529c443d89951a693e3514789a69347c969f24a0c6793cce15fdb798e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for prosedown-0.6.1-py3-none-any.whl:

Publisher: release.yml on jeffalldridge/prosedown

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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