Install and project layout
Requirements
Required
- PHP 8.2+ with extensions
dom,gd,mbstring,zip, andzlib - Composer
Optional
| Tool | Used by | Notes |
|---|---|---|
mmdc (@mermaid-js/mermaid-cli or Homebrew mermaid-cli) |
Mermaid diagrams | Needs Chrome/Chromium for Puppeteer |
| Chrome or Chromium | Mermaid CLI | Set PUPPETEER_EXECUTABLE_PATH if needed |
epubcheck |
kdp:ebook |
Extra validation; skipped with a warning when absent |
macOS (Homebrew)
brew install php composer
brew install mermaid-cli
brew install --cask google-chrome
brew install epubcheck
export PUPPETEER_EXECUTABLE_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
npm / Linux
npm install -g @mermaid-js/mermaid-cli
# Debian/Ubuntu example:
sudo apt-get install -y chromium-browser
export PUPPETEER_EXECUTABLE_PATH="$(command -v chromium-browser || command -v google-chrome || command -v chromium)"
Install epubcheck and put it on
PATH, or use brew install epubcheck on macOS.
Check the toolchain
php -m | grep -E 'dom|gd|mbstring|zip|zlib'
mmdc --version
epubcheck --version
papyrus doctor
Install per project
In your book repository:
composer require milon/papyrus
vendor/bin/papyrus --version
vendor/bin/papyrus init
vendor/bin/papyrus doctor
PHAR (no Composer project)
From GitHub Releases, download papyrus.phar. You still need PHP 8.2+ with the extensions above — not Composer.
curl -L -o papyrus.phar https://github.com/milon/papyrus/releases/download/v1.5.0/papyrus.phar
chmod +x papyrus.phar
php papyrus.phar --version
php papyrus.phar build:site -d path/to/book
In CI for a non-PHP repo, install PHP (for example shivammathur/setup-php),
download the PHAR, and run php papyrus.phar …. Full Composer and PHAR
workflow examples are in CI for documentation.
Wire 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",
"doctor": "papyrus doctor"
}
}
Package page: packagist.org/packages/milon/papyrus.
Install globally
composer global require milon/papyrus
export PATH="$(composer global config bin-dir --absolute):$PATH"
papyrus list
Scaffold a book
papyrus init
papyrus init -d my-book
papyrus init --format=yml
papyrus init --format=yaml
papyrus init --format=json
init creates a book config (papyrus.php by default, or YAML / JSON via
--format), content/, and an empty assets/ directory.
Papyrus uses bundled themes, CSS, and fonts by default. Publish those files
into your project only when you want to customize them:
papyrus asset:publish
papyrus asset:publish --only=themes,css
Use --force / -f to overwrite files during init, or with
asset:publish to overwrite published assets. --only limits publishing to
themes, css, and/or fonts.
Scaffold a documentation site
For a library or tool (not a print book), use the docs preset:
papyrus init --preset=docs
papyrus init --preset=docs -d docs
That writes papyrus.yml by default (override with --format=php|json),
starter chapters (welcome, install, usage, reference, changelog), an empty
assets/, and a sample GitHub Actions workflow under
github/workflows/docs-site.yml (copy it to .github/workflows/).
If a composer.json is found in the target directory or its parent, Papyrus
fills title, site.lead, site.links (GitHub / Packagist),
site.repository / site.edit (for Edit this page), and a suggested
site.base_path (e.g. /barcode for milon/barcode). There is no KDP or
sample-PDF config in this preset.
papyrus build:site -e docs
papyrus serve -s docs/<slug>-site
The site home always uses a Get started CTA (preferring Install / quick-start
chapters) with secondary links below. Set author on the project if you want
the author line on Home. Older site.mode: book|docs values are ignored.
Import an existing README
Most PHP packages start as one fat README.md. Split it into chapters on
## headings:
papyrus import-readme
papyrus import-readme --file ../README.md --dry-run
papyrus import-readme -d docs --force
Then update site.nav to match the new files.
Typical docs-site config
After init --preset=docs (or import-readme), a package docs root usually looks
like:
# papyrus.yml
title: milon/barcode
site:
lead: Short pitch for the home page.
base_path: /barcode # omit with a custom domain / cname
repository: https://github.com/milon/barcode
edit:
link: true # default false
path: docs-src/content # path from repo root to content/
branch: master # default main
links:
- { label: GitHub, url: https://github.com/milon/barcode }
- { label: Packagist, url: https://packagist.org/packages/milon/barcode }
nav:
- group: Getting started
chapters: [00-welcome.md, 01-installation.md, 02-quick-start.md]
- group: API
chapters: [04-output-methods.md, 06-examples-with-screenshots.md]
Optional multi-version peers (each version is its own build:site):
site:
version: v12
versions:
- { label: v12, path: /barcode/v12 }
- { label: v11, path: /barcode/v11 }
Full key tables live in Configuration and build:site.
Config without PHP (YAML or JSON)
You still need PHP installed to run Papyrus — but you do not need to edit PHP to configure a book. If you are more comfortable with YAML or JSON, scaffold that way:
papyrus init --format=yml # writes papyrus.yml (--format=yaml is the same)
papyrus init --format=json # writes papyrus.json
Same keys as the PHP stub, without the <?php return […] wrapper. Example
YAML:
title: My Book
subtitle: A short subtitle
author: Author Name
themes:
- light
- dark
document:
size: crown-quarto
margin_left: 27
margin_right: 27
margin_top: 14
margin_bottom: 14
toc:
h1: 0
h2: 0
h3: 1
mermaid:
enabled: true
format: svg
theme: auto
Or JSON:
{
"title": "My Book",
"subtitle": "A short subtitle",
"author": "Author Name",
"themes": ["light", "dark"],
"document": {
"size": "crown-quarto",
"margin_left": 27,
"margin_right": 27,
"margin_top": 14,
"margin_bottom": 14
}
}
Rules of thumb:
- Keep exactly one config file in the book root (
papyrus.php,papyrus.yml/papyrus.yaml, orpapyrus.json). --format=ymland--format=yamlboth writepapyrus.yml.- You can also name the file
papyrus.yamlby hand; Papyrus loads either extension. - Full option tables live in the Configuration chapter — they apply to every format.
- One PHP-only escape hatch:
configure_commonmark(a callable). If you need that hook, usepapyrus.php; otherwise YAML/JSON are enough.
Coming from ibis-next, the same choice exists on migrate:
papyrus migrate-ibis --format=yml\
papyrus migrate-ibis --format=json
Layout
| Path | Role |
|---|---|
papyrus.php / .yml / .yaml / .json |
Book settings (exactly one) |
content/ |
Markdown chapters |
assets/ |
Your overrides: themes, CSS, covers, fonts, banner |
export/ |
Built artifacts |
.papyrus/ |
Incremental caches |
Only one config file is allowed. See Config without PHP
above if you prefer YAML or JSON. Use papyrus.php when you need PHP callables
such as configure_commonmark.
Always run from the book root, or pass -d / --dir. Override where
artifacts are written with -e / --export (default: <book>/export):
papyrus doctor -d /path/to/book
papyrus build --dir /path/to/book
papyrus build:site -d /path/to/book -e /path/to/out
Browse the Papyrus source on
GitHub if you want to follow along with
this handbook’s own project under examples/the-papyrus-handbook/.