Source for the book Learn Ruby on Rails by Stefan Wintermeyer, targeting Ruby 4.0 and Ruby on Rails 8.1.
The book is built with Antora. The visual
chrome (Tailwind v4 theme, sidebars, TOC, pagination, mobile nav)
comes from the shared UI bundle at
wintermeyer/wincon-antora-ui,
which is also used by the Phoenix book at /phoenix/book/ — so both
books feel like one publication.
The wincon top nav and site-wide footer are pulled at build time
from
wincon/priv/static/partials/
by scripts/fetch-partials.sh, which stamps
data-book-current="rails" into the nav so the Rails link is
highlighted. The fetched HTML lands in ui-supplemental/partials/
and Antora's ui.supplemental_files overlay substitutes it for the
UI bundle's default header-content.hbs / footer-content.hbs.
Dark mode follows prefers-color-scheme. System fonts only (Georgia
for headings, system sans for body, ui-monospace for code).
antora.yml # component descriptor
antora-playbook.yml # production site playbook (pulls remote content)
antora-local-playbook.yml # local dev: this working copy as source
modules/
ROOT/
nav.adoc # sidebar structure
pages/*.adoc # one chapter per file
images/screenshots/ # referenced via image::screenshots/...
scripts/
deploy.sh # self-hosted runner build + atomic swap
fetch-partials.sh # pull wincon nav + footer at build time
docs/nginx.md # one-time bremen2 nginx setup
ui-supplemental/ is gitignored — it's generated at every deploy.
- Node 20+
npm install
npx antora --fetch antora-local-playbook.yml # renders into build/site/--fetch pulls the UI bundle from
https://github.com/wintermeyer/wincon-antora-ui/releases/download/latest/ui-bundle.zip.
Open build/site/book/index.html in a browser to preview.
To refresh the nav + footer from the live wincon server before the
build (optional — without this the UI bundle's default empty
data-book-current is used and nothing is highlighted):
./scripts/fetch-partials.shPushing to main triggers .github/workflows/deploy.yml, which
runs on the dedicated self-hosted runner (label books) on bremen2.
The runner checks the repo out and executes scripts/deploy.sh:
- Activate mise (Node pinned via
.tool-versionson the runner's profile; no repo-local pin anymore). scripts/fetch-partials.sh— pulls canonical nav + footer from wincon intoui-supplemental/.npm ciinstalls Antora.npx antora --fetch antora-playbook.ymlrenders intobuild/site/; the UI bundle is pulled from wincon-antora-ui.- Copy
build/site/→/var/www/rails-book/releases/<ts>/. - Pre-compress every text asset (
.html,.css,.js,.svg,.xml,.json,.mjs,.txt,.map) into.br(brotli q11) and.gz(gzip -9) siblings so nginx'sbrotli_static/gzip_staticcan serve them with zero CPU on the hot path. - Atomically swap the
currentsymlink. - Prune old releases (keep last 5).
Nginx on bremen2 serves /rails/book/ from
/var/www/rails-book/current/book/ and
/rails/antora-assets/ from …/current/antora-assets/ (see
docs/nginx.md).
See individual files for attribution.