with one click
building-docs
// How to build, preview, and verify Quarkus documentation locally: root Maven build, docs rebuild, Jekyll preview via Podman/Docker.
// How to build, preview, and verify Quarkus documentation locally: root Maven build, docs rebuild, Jekyll preview via Podman/Docker.
| name | building-docs |
| description | How to build, preview, and verify Quarkus documentation locally: root Maven build, docs rebuild, Jekyll preview via Podman/Docker. |
This workflow is supported on Linux, macOS, and Windows through WSL2. Native Windows shells (PowerShell, CMD, Git Bash) are not supported.
Run the full pipeline in one command:
just docs-preview
The script uses local marker files to keep the preview workflow fast:
docs/.docs-preview-root-build-last-run — last successful root build.
Used to decide whether Step 1 can be skipped.docs/.docs-preview-root-build-head — Git HEAD at last root build.
Detects branch switches, checkouts, and pulls.docs/.docs-preview-docs-build-last-run — last successful docs rebuild.
Used to decide whether Step 2 can be skipped.docs/.docs-preview-last-run — last preview run.
Used to detect recently changed files and open the right preview URL.docs/.docs-preview-times — cached execution times for progress estimates.All marker files are gitignored. Delete them to force a full rebuild.
Caveat: The script detects changes to docs sources and pom.xml files,
but does not detect uncommitted changes outside docs/ (e.g., new config
properties, extension metadata, or generated-doc producers). If you modify
code that affects generated documentation, force a root build manually:
QUARKUS_DOCS_PREVIEW_FULL=1 just docs-preview
Source detect-env.sh to set $CONTAINER_CMD, $VOL_FLAG,
$MVN_THREADS, $MAVEN_OPTS, and $BROWSER_CMD:
. docs/detect-env.sh
The script computes Maven heap, thread count, container runtime, and browser automatically based on your machine.
Run once, then re-run roughly once a week, after pulling significant upstream changes, or when Step 2 fails.
Use -DquicklyDocs, not -Dquickly (which sets skipDocs=true).
The extra flags are not covered by the profile and are needed to skip
integration-test modules, Gradle plugin build, and javadoc generation.
./mvnw $MVN_THREADS clean install -DquicklyDocs \
-Dno-test-modules -Dskip.gradle.build=true -Dmaven.javadoc.skip=true
Fallback (single-threaded) if the parallel build fails:
./mvnw clean install -DquicklyDocs \
-Dno-test-modules -Dskip.gradle.build=true -Dmaven.javadoc.skip=true
docs/)cd docs
../mvnw -ntp package -Dasciidoctor.fail-if=ERROR # quick rebuild (~1 min)
../mvnw -ntp clean package -Dasciidoctor.fail-if=ERROR # if output looks stale
The -Dasciidoctor.fail-if=ERROR override lets the build succeed despite
AsciiDoctor warnings (the default WARN level fails on cross-reference
or attribute warnings that are harmless for local preview).
docs/)First time: ./sync-web-site.sh
Subsequent iterations — fast re-sync (<1 second). This duplicates the
rsync portion of sync-web-site.sh to skip its rm -rf + git clone
(~4 min). If sync-web-site.sh gains a --no-clone flag, prefer that.
rsync -rt --delete \
--exclude='**/*.html' --exclude='**/index.adoc' \
--exclude='**/_attributes-local.adoc' --exclude='**/guides.md' \
--exclude='**/_templates' \
target/asciidoc/sources/ target/web-site/_versions/main/guides
[ -d target/quarkus-generated-doc/ ] && rsync -rt --delete \
--exclude='**/*.html' --exclude='**/index.adoc' \
--exclude='**/_attributes.adoc' \
target/quarkus-generated-doc/ target/web-site/_generated-doc/main
if [ -f target/indexByType.yaml ]; then
mkdir -p target/web-site/_data/versioned/main/index
{ echo "# Generated file. Do not edit"; cat target/indexByType.yaml
} > target/web-site/_data/versioned/main/index/quarkus.yaml
fi
if [ -f target/relations.yaml ]; then
mkdir -p target/web-site/_data/versioned/main/index
{ echo "# Generated file. Do not edit"; cat target/relations.yaml
} > target/web-site/_data/versioned/main/index/relations.yaml
fi
docs/target/web-site)The --config flag chain loads _only_latest_guides_config.yml (excludes
old version directories) and _config_dev.yml (uses staging search
cluster). These files come from the quarkusio.github.io repository,
cloned into target/web-site/ by sync-web-site.sh.
Primary — build from the upstream jekyll-container/ Dockerfile
(available after sync). This matches what quarkusio.github.io uses in
production and eliminates external image dependencies:
cd target/web-site
$CONTAINER_CMD build -t quarkus-docs-jekyll:local jekyll-container/
$CONTAINER_CMD run -d --name quarkus-docs-preview \
-p 127.0.0.1:4000:4000 -p 127.0.0.1:35729:35729 \
-v "$(pwd):/site${VOL_FLAG}" \
-v quarkus-jekyll-bundles:/usr/local/bundle \
quarkus-docs-jekyll:local \
bundle exec jekyll serve --host 0.0.0.0 \
--livereload --incremental \
--config _config.yml,_config_dev.yml,_only_latest_guides_config.yml
Stop: $CONTAINER_CMD rm -f quarkus-docs-preview
Fallback — pre-built images (pinned by digest) if the local build is not available (e.g., first run before sync completes):
# Fallback 1: bretfisher/jekyll-serve
$CONTAINER_CMD run -d --name quarkus-docs-preview \
-p 127.0.0.1:4000:4000 -p 127.0.0.1:35729:35729 \
-v "$(pwd):/site${VOL_FLAG}" \
-v quarkus-jekyll-bundles:/usr/local/bundle \
docker.io/bretfisher/jekyll-serve@sha256:db11b70736935b1a777b2ff2ae10f9ad191ee9fca6560eade1d5ad98b74e5f66 \
bundle exec jekyll serve --host 0.0.0.0 \
--livereload --incremental \
--config _config.yml,_config_dev.yml,_only_latest_guides_config.yml
# Fallback 2: jekyll/jekyll (mount at /srv/jekyll)
$CONTAINER_CMD run -d --name quarkus-docs-preview \
-p 127.0.0.1:4000:4000 -p 127.0.0.1:35729:35729 \
--volume="$(pwd):/srv/jekyll${VOL_FLAG}" \
-v quarkus-jekyll-bundles:/usr/local/bundle \
docker.io/jekyll/jekyll@sha256:bb45414c3fefa80a75c5001f30baf1dff48ae31dc961b8b51003b93b60675334 \
bundle exec jekyll serve --host 0.0.0.0 \
--livereload --incremental \
--config _config.yml,_config_dev.yml,_only_latest_guides_config.yml
The script auto-detects what you were working on and opens the right page:
| Content type | How detected | Preview URL |
|---|---|---|
| 1 guide | Recently modified .adoc in docs/src/main/asciidoc/ | /version/main/guides/<name>.html (direct) |
| 2-4 guides | Multiple .adoc files modified | Opens a tab for each guide |
| 5+ guides | Many files modified | /version/main/guides/ (listing) |
| Blog post | Recently modified _posts/*.adoc, no user-story tag | /blog/<slug>/ (deep-link) |
| User story | Recently modified _posts/*.adoc, has user-story tag | /blog/<slug>/ (deep-link) |
| No changes | No recent .adoc changes found | / (homepage) |
Edit .adoc → save → Step 2 (~1 min) → Step 3 re-sync (<1s) → browser auto-refreshes
Container stays running. Escalate to Step 1 when Step 2 fails or after significant upstream changes.
| Symptom | Action |
|---|---|
| Quick rebuild succeeds but content looks stale | Try ../mvnw -ntp clean package -Dasciidoctor.fail-if=ERROR in docs/ |
clean package still broken or fails | Root build (Step 1) |
Pulled new upstream changes to main | Root build (Step 1) |
| Root build is roughly a week old | Root build (Step 1) |
| New config properties or extensions added | Root build (Step 1) |
Failed to delete docs/.cache/formatter-maven-cache.properties —
Rootless Podman UID mapping. Fix: podman unshare rm -rf docs/.cache/.
With Docker: rm -rf docs/.cache/.
Volume mount errors on macOS/Ubuntu — SELinux :z flag applied on
a system without SELinux. Source detect-env.sh to set $VOL_FLAG
correctly.
Container image pull fails — The script first tries to build from the
upstream jekyll-container/ Dockerfile, then falls back to pre-built images
pinned by digest. To force a rebuild of the local image:
$CONTAINER_CMD rmi quarkus-docs-jekyll:local
Preview shows partial or stale content — Jekyll's --incremental
mode can sometimes miss dependency changes. Restart the container
($CONTAINER_CMD rm -f quarkus-docs-preview) and run just docs-preview
again. If that doesn't help, delete docs/target/web-site/.jekyll-cache
before re-running.
Force a full root build — Set QUARKUS_DOCS_PREVIEW_FULL=1 before
running: QUARKUS_DOCS_PREVIEW_FULL=1 just docs-preview
Quarkus code style conventions: formatting, visibility, naming, logging, and general style rules for the Quarkus codebase.
Testing patterns for Quarkus extensions: test annotations, test locations, QuarkusExtensionTest patterns, and how to run tests.
How to add a Dev UI page to a Quarkus extension: deployment processors, runtime-dev JSON-RPC services, and Lit web components.
How to build and test Quarkus: Maven commands, build flags, incremental builds, justfile aliases, and important build rules.
Rules for preparing pull requests and commits in the Quarkus project: title conventions, description format, commit hygiene, labels, and contribution policies.
Quarkus split classloading model, runtime-dev module wiring, conditional dependencies, and common classloading mistakes.