This directory builds LaraFly by Example, a bilingual (EN + ES) book teaching
LaraFly by walking through the samples/lumen project chapter by chapter. It
mirrors fireflyframework-pyfly/book/'s architecture (WeasyPrint -> PDF, a
hand-rolled EPUB3 assembler, python-markdown with custom directives), renamed
and re-tokened for LaraFly/PHP/Laravel.
This is a Python toolchain, isolated from the PHP monorepo: book/.venv/
and book/dist/ (the generated PDF/EPUB) are gitignored and never committed.
Only the sources — book.yaml, build/*.py, theme/*.css, art/,
src/ (EN), src-es/ (ES), tests/ — are tracked.
The first build needs network access (to install the Python deps) and a native cairo + pango stack (WeasyPrint's rendering backend). Every build after that is fully offline.
# 1. Create the venv (Python 3.12 preferred; this repo used 3.13 — 3.12 was not
# installed on the build machine, and WeasyPrint has no 3.12-specific pin).
python3.12 -m venv book/.venv # or: python3.13 -m venv book/.venv
book/.venv/bin/pip install -r book/build/requirements.txt
# 2. macOS only: WeasyPrint links against cairo/pango via ctypes at runtime.
brew install cairo pangobook/build/run.sh sets DYLD_FALLBACK_LIBRARY_PATH to Homebrew's lib/ so
WeasyPrint finds libcairo/libpango without any manual export. On Linux,
install the equivalent packages (e.g. apt install libcairo2 libpango-1.0-0)
and run.sh's DYLD_FALLBACK_LIBRARY_PATH export is a no-op (Linux uses the
system loader path instead).
bash book/build/run.sh # English -> book/dist/larafly-by-example.{pdf,epub}
bash book/build/run.sh --config book.es.yaml # Spanish -> book/dist/larafly-by-example-es.{pdf,epub}book/dist/ is created on demand and is gitignored — nobody commits a
generated PDF/EPUB.
Every fenced ```php block in the manuscript is linted with the real PHP
CLI (php -l, via a temp file — no execution):
book/.venv/bin/python book/build/verify_code.py book/src
book/.venv/bin/python book/build/verify_code.py book/src-esExits non-zero and prints FAIL <file>:<line> ... for any listing that fails
to parse.
cd book && ../book/.venv/bin/python -m pytest -qCovers the Markdown extension (::: figure, ::: listing, admonitions), the
EPUB3/OCF assembler, and the PHP-listing extractor/linter.
book/
book.yaml # EN manifest: title/author/rights, front matter, parts/chapters
book.es.yaml # ES manifest (manuscript_dir: src-es)
build/
build.py # orchestrates: manifest -> items -> EpubBuilder + render_pdf
md.py # Markdown -> XHTML: ::: figure / ::: listing directives,
# note/tip/warning/laravel admonitions, codehilite
epub.py # stdlib-only EPUB3 (OCF) zip assembler
pdf.py # WeasyPrint HTML -> PDF
gen_cover.py # regenerates art/cover.{svg,png} (firefly/spark motif)
verify_code.py # extracts fenced ```php listings, lints with `php -l`
run.sh # sets DYLD_FALLBACK_LIBRARY_PATH, execs build.py
requirements.txt # pinned: weasyprint, markdown, pygments, pyyaml, pytest, cairosvg
theme/
tokens.css # CSS custom properties (palette)
book.css # shared screen/EPUB styles
print.css # @page rules, running heads, page-break control (PDF only)
pygments.css # syntax-highlighting token colors
art/
cover.svg, cover.png # generated by gen_cover.py
figures/ # inline-SVG diagrams referenced by ::: figure
openers/ # reserved for future per-chapter opener art (empty)
src/ # EN manuscript (Markdown)
00-front/ # title/copyright/dedication/preface/conventions
00-quickstart.md # "Build Lumen step by step" quick start
01..13-*.md # the thirteen chapters (Parts I-IV)
90-appendix-a-laravel.md # Laravel -> LaraFly cheat-sheet
94-glossary.md # glossary
src-es/ # ES manuscript, same structure/filenames
tests/
test_md.py, test_epub.py, test_verify_code.py
- Code listings: real chapters use a plain fenced block with the language
tag
php, e.g.```php. These are both syntax-highlighted (via Pygments) and linted byverify_code.py. A custom::: listing <label> | <caption>block directive is also available (ported from PyFly) for listings that need a file-name tab and a numbered caption baked into the HTML. - Figures:
::: figure <path.svg> | <caption>inlines an SVG (or embeds a raster image as a data URI) so it renders crisply in both the EPUB and the print PDF. - Callouts:
!!! note,!!! tip,!!! warning(admonition extension), and LaraFly's own!!! laravel "..."— a Laravel-parity callout that maps a LaraFly concept directly to its native Laravel equivalent (this replaces PyFly's!!! springcallout).
The manuscript is complete in both languages: a five-file front matter, a "Build Lumen step by step" quick start, thirteen chapters across four parts —
- Part I — Foundations: Why LaraFly, Dependency Injection & Auto-Configuration, Configuration/Profiles/Secrets, Your First HTTP API
- Part II — Modelling & Persisting the Domain: Persistence & Repositories, Domain-Driven Design
- Part III — Coordinating & Securing the Application: CQRS, Event-Driven
Architecture & the Transactional Outbox, Transactions & the
#[Transactional]proxy, Security - Part IV — Observability, Testing & Delivery: Observability/Actuator, Testing, the CLI & the Zero-Reflection Cache
— plus Appendix A (Laravel → LaraFly cheat-sheet) and a Glossary. Every
chapter walks the real samples/lumen project, and every fenced ```php
listing is php -l-clean (enforced by verify_code.py over both src/ and
src-es/). Both editions build to book/dist/ as PDF + EPUB.