milon / papyrus
PHP CLI for Markdown book projects — PDF, EPUB, HTML, multi-page site, and Amazon KDP exports
Package info
pkg:composer/milon/papyrus
Requires
- php: ^8.2
- ext-dom: *
- ext-gd: *
- ext-mbstring: *
- ext-zip: *
- ext-zlib: *
- hi-folks/phpepub: ^1.0
- league/commonmark: ^2.7
- mpdf/mpdf: ^8.2
- spatie/commonmark-highlighter: ^3.0
- symfony/console: ^7.2
- symfony/yaml: ^7.2
Requires (Dev)
- laravel/pint: ^1.21
- phpunit/phpunit: ^11.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
PHP CLI for Markdown book projects — PDF, EPUB, HTML, Hosted Site, and KDP exports.
Built from scratch with heavy influence from ibis-next. Book projects use papyrus.php, content/, and assets/. By default Papyrus uses bundled themes, CSS, and fonts; publish them into your project only when you want to customize them.
Beyond ibis-next
Same core idea — Markdown chapters to PDF, EPUB, and HTML — plus first-class extras that ibis-next does not ship:
- Multi-page site —
build:sitewith Home, chapter sidebar, popup search, heading permalinks, sitemap/robots, Prev/Next, light/dark mode, banner, and404.html(ready for GitHub Pages / Netlify) - Local preview —
serveruns the site withphp -Sso search and assets work over HTTP - Amazon KDP — Kindle EPUB, print interior (bleed + margins), cover export, wraparound cover PDF, wrap-size estimates, metadata JSON, upload package zip (
kdp/kdp:*) - Draft chapters —
draft: truein front matter omits chapters from builds unless--include-drafts - Mermaid —
mermaidfences rendered at build time for PDF, EPUB, HTML, and site (theme: autoembeds light + dark on the web) - Sample PDFs — carve marketing / review PDFs from page ranges and/or whole chapters (
build:sample) - Multi-script fonts — ordered script → face routing for PDF (e.g. Bengali alongside Latin)
- Parallel PDF themes —
build:pdf --parallelfor light + dark in one go - Tooling —
doctor,watch,serve, PHP fencelint, page-sizesizes,asset:publish, andmigrate-ibisfromibis.php - Caches — incremental chapter HTML and Mermaid figure caches under
.papyrus/ - Export override —
-e/--exportto write artifacts outside the book tree (CI /docs/)
See the handbook for the full option set.
Stability (1.x)
Starting with 1.0, Papyrus treats these as stable for SemVer majors:
- CLI command names and common flags (
-d,-e,--include-drafts, …) papyrus.phppublic config keys documented in the handbook- Default export filenames under
export/
Theme HTML, CSS, and internal PHP APIs may still change in minor releases when needed for fixes or features.
Host your book as a website
build:site turns the same Markdown chapters into a multi-page static site you can deploy anywhere (GitHub Pages, Netlify, S3, …):
papyrus build:site # → export/<slug>-site/ papyrus serve # → http://127.0.0.1:8000/ (popup search needs a real HTTP origin) papyrus serve -s docs/the-papyrus-handbook-site
What you get:
- One HTML page per chapter, plus a Home index
- Chapter sidebar (collapsible on mobile)
- Popup search (
/or the topbar button; ↑/↓/Enter; ranked title/heading hits) - Light and dark mode (same palette as single-file HTML)
- Prev / Next navigation between chapters
sitemap.xml,robots.txt, and optionalCNAME/site.base_path- Shared
assets/site.cssandassets/site.js— no CDN required
Example — this repo’s handbook is hosted on GitHub Pages:
papyrus build:site -d examples/the-papyrus-handbook -e docs
Handbook
The sample book The Papyrus Handbook lives in examples/the-papyrus-handbook/. Read it online or from the prebuilt exports in docs/:
- Site — GitHub Pages (sidebar, popup search, light/dark mode)
- Downloads — full and sample PDF previews from GitHub
- HTML — single file, light/dark mode toggle
- PDF (light) · PDF (dark)
- Sample PDF (light) · Sample PDF (dark)
Rebuild those exports with:
composer build:handbook
That runs build:pdf, build:sample, build:html, and build:site with
-d examples/the-papyrus-handbook -e docs.
Requirements
Required
- PHP 8.2+ with extensions
dom,gd,mbstring,zip, andzlib(PDF via mPDF; EPUB packaging) - Composer
Optional (features work without them; Papyrus skips or warns when missing)
| Tool | Used by | Notes |
|---|---|---|
@mermaid-js/mermaid-cli (mmdc) |
Mermaid diagrams | Needs a Chrome/Chromium binary for Puppeteer |
| Chrome or Chromium | Mermaid CLI | Set PUPPETEER_EXECUTABLE_PATH if the bundled browser is missing |
epubcheck |
kdp:ebook |
Extra EPUB validation; skipped with a warning when absent |
Install optional tooling (macOS / Homebrew)
brew install php composer brew install mermaid-cli # provides mmdc brew install --cask google-chrome # Puppeteer browser for Mermaid brew install epubcheck # optional KDP EPUB checks (pulls OpenJDK)
Point Mermaid at system Chrome when needed:
export PUPPETEER_EXECUTABLE_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
Install optional tooling (npm / Linux)
# Mermaid CLI (global, or use npx - Papyrus also tries `npx -y @mermaid-js/mermaid-cli`) npm install -g @mermaid-js/mermaid-cli # Browser for Puppeteer (pick one) # Debian/Ubuntu: sudo apt-get install -y chromium-browser # or Google Chrome from Google’s .deb export PUPPETEER_EXECUTABLE_PATH="$(command -v chromium-browser || command -v google-chrome || command -v chromium)" # epubcheck — Homebrew on macOS, or download from # https://github.com/w3c/epubcheck/releases and put `epubcheck` on PATH
Verify:
php -m | grep -E 'dom|gd|mbstring|zip|zlib' mmdc --version epubcheck --version papyrus doctor
Install
Per project (recommended)
In your book repository:
composer require milon/papyrus
Then run via Composer’s binary path:
vendor/bin/papyrus --version vendor/bin/papyrus init
Or add Composer scripts (example):
{
"scripts": {
"build": "papyrus build",
"build:pdf": "papyrus build:pdf --theme light,dark",
"build:epub": "papyrus build:epub",
"build:html": "papyrus build:html",
"build:site": "papyrus build:site",
"build:sample": "papyrus build:sample",
"build:kdp": "papyrus kdp"
}
}
composer build composer build:site
Global CLI
composer global require milon/papyrus
Ensure Composer’s global bin directory is on your PATH (typical locations: ~/.composer/vendor/bin or ~/.config/composer/vendor/bin):
export PATH="$(composer global config bin-dir --absolute):$PATH" papyrus --version papyrus list
From this repository (development)
composer install ./bin/papyrus --version ./bin/papyrus list
Quick start
Scaffold a new book in the current directory:
papyrus init papyrus doctor papyrus build:site
Or in a new folder:
mkdir my-book && papyrus init -d my-book
papyrus doctor -d my-book
papyrus build:site -d my-book
Open export/<slug>-site/index.html in a browser, or deploy that folder as a static site.
init creates an empty assets/ directory. To customize the bundled theme or
fonts later:
papyrus asset:publish papyrus asset:publish --only=themes
Commands
| Command | Description |
|---|---|
init |
Scaffold papyrus.php, content/, and an empty assets/ |
asset:publish |
Publish bundled themes, CSS, and fonts into assets/ (--only, --force) |
doctor |
Validate config, assets, Mermaid, KDP readiness |
build |
Build PDF/EPUB/HTML/KDP; optional --with-site / --with-sample |
build:pdf |
Build PDF themes (--theme light,dark, --parallel for multi-theme) |
build:site |
Multi-page HTML site (sidebar, search, sitemap, light/dark) |
serve |
Serve the site locally with php -S (--host, --port, --build, --site) |
build:html |
Build single-file HTML from assets/theme-html.html (light/dark mode) |
build:epub |
Build EPUB3 with CSS and embedded images |
build:sample |
Build sample PDF from sample.ranges and/or sample.chapters |
kdp |
All enabled KDP outputs (--require-epubcheck, --package, --wrap) |
kdp:ebook |
KDP-ready Kindle EPUB (export/<slug>-kdp.epub) |
kdp:print |
Print interior PDF with KDP margin/bleed presets |
kdp:cover |
Export KDP cover assets (--dimensions, --wrap, --pages, --theme) |
kdp:metadata |
Emit KDP metadata sidecar JSON |
kdp:package |
Zip enabled KDP artifacts with an upload checklist |
sizes |
List KDP page-size presets |
migrate-ibis |
Migrate ibis.php to papyrus.php; update TOC markers in local themes |
lint |
Lint PHP code fences in content/ (--fix to auto-fix) |
watch |
Rebuild on file changes (--interval, --with-site, --with-sample, --include-drafts) |
Common options on book commands:
-d/--dir— book root (default: current directory)-e/--export— override export directory (default:<book>/export)--include-drafts— include chapters withdraft: truein front matter
Convert Markdown chapters programmatically:
$project = Milon\Papyrus\Config\Project::load($bookDir); $book = $project->bookWithFigures(breakLevel: 1, exportTheme: 'html'); // drafts omitted $withDrafts = $project->withIncludeDrafts()->bookWithFigures(breakLevel: 1, exportTheme: 'html');
Tests
composer test composer lint # Pint composer format # Pint --write
Changelog
See CHANGELOG.md for release notes and upgrade guidance.
License
MIT — see LICENSE.
