Juicer
English

CLI

The juicer command-line tool — build, serve, config, theme.

Juicer’s CLI has four subcommands: build, serve, config, and theme (with add / upgrade sub-subcommands). Every command runs on JVM, Scala.js (Node), and Scala Native — serve and its live-reload watcher use microserve for cross-platform HTTP and file-watching.

Global options

These apply to every subcommand. Place them before the subcommand name on the command line:

FlagWhat
-b, --baseurl <URL>Override baseURL from the config — typically used in CI for environment-specific URLs (https://staging.example.com/ vs https://example.com/).
-c, --config <name>Pick a baseline config: simple, standard (default), or norme. Your site.toml overlays on top of the chosen baseline.
-h, --helpPrint usage and exit.
-v, --verbosePrint step-by-step build progress — layout selection, file walks, what’s being written where. Indispensable when a page is being silently skipped.
--versionPrint the version and exit.
sbt 'juicerJVM/run --baseurl https://staging.example.com/ build -s docs'
sbt 'juicerJVM/run --config simple build -s notes'
sbt 'juicerJVM/run -v build -s docs'

build

Render the site to disk. Output goes to <src>/<publicDir> (default <src>/public/) unless -d overrides.

sbt 'juicerJVM/run build -s docs'
sbt 'juicerJVM/run build -s docs -d _site -b https://juicer.build/'
sbt 'juicerJVM/run build -s blog -D -F'
FlagDefaultWhat
-s, --source <p>.Site source directory.
-d, --dest <p><src>/<publicDir>Output directory. Overrides the publicDir config key.
-D, --draftsoffInclude pages with draft: true frontmatter. Drafts are normally invisible to every downstream consumer — TOC, sitemap, search index, section listings.
-F, --futureoffInclude pages whose parsed date: is past the current build time. Future-skip applies only to pages with explicit date: frontmatter — mtime-fallback dates are never future-skipped. Pages in the eventsSection (default events) are also exempt from future-skip.
Tip

The classic CI build, e.g. for a GitHub Pages workflow:

sbt 'juicerJVM/run build -s docs -d _site -b https://example.github.io/repo/'

serve

Build the site once, then serve it on localhost. Optionally watch the source and rebuild on every change.

sbt 'juicerJVM/run serve -s docs'
sbt 'juicerJVM/run serve -s docs -L'
sbt 'juicerJVM/run serve -s docs --host 0.0.0.0 -p 4000'
FlagDefaultWhat
-s, --source <p>.Site source directory.
-d, --dest <p><src>/<publicDir>Output directory. Excluded from the live-reload watch loop so builds don’t trigger themselves.
--host <h>localhostBind host. Use 0.0.0.0 to expose the dev server on the LAN.
-p, --port <p>8080Listen port. If the port is already bound, juicer scans up to 20 ports upward (:8081, :8082, …) and prints the actual port it landed on.
-D, --draftsoffInclude drafts (same semantics as build -D).
-F, --futureoffInclude future-dated pages (same semantics as build -F).
-L, --live-reloadoffWatch the source recursively, rebuild on change, and live-reload connected browser tabs.

Live reload — how it works

When -L is on, every HTML response gets a tiny long-polling client script injected before </body>. The script calls GET /__juicer/wait?since=<version>; the server holds each poll open until the next rebuild (or 30s, whichever comes first) and responds with {reload, version}. The client calls location.reload() on reload: true.

Long-polling — not SSE — was chosen because SSE leaks a connection during page-unload across browsers, and HTTP/1.1 connection-limit pooling makes the failure mode look like “live-reload silently stopped working.” A fresh fetch per cycle has neither problem.

The watcher is debounced at 150ms, so saving five files in rapid succession results in one rebuild and one reload. Saves to the output directory (-d) are ignored to prevent build-triggers-itself loops.

config

Print the resolved configuration after the chosen baseline, site.toml overlay, and CLI overrides are merged. Useful for debugging “why is htmlDir doing that?” — the answer is right there in the printed config.

sbt 'juicerJVM/run config -s .'
sbt 'juicerJVM/run --config simple config -s notes'
FlagDefaultWhat
-s, --source <p>.Site source directory.

theme add

Install a theme from a git repository into <src>/<themeDir>/. After running it, set theme = "<name>" in your site.toml to activate.

sbt 'juicerJVM/run theme add https://github.com/edadma/juicer.git -n juicerdocs'
sbt 'juicerJVM/run theme add https://github.com/me/my-theme.git -r v1.2.0'
sbt 'juicerJVM/run theme add https://github.com/edadma/juicer.git -n juicerblog --subdir docs/themes/juicerblog'
FlagDefaultWhat
<git-url> (positional)requiredHTTPS or SSH URL of the theme repository.
-s, --source <p>.Site source directory. The theme is installed under <src>/<themeDir>/.
-n, --name <name>derived from URL/subdirDirectory name to install under. Required when juicer can’t infer a sensible name from the URL.
-r, --ref <ref>repo HEADBranch, tag, or commit SHA to check out. Lock to a tag for reproducible builds.
--subdir <path>repo rootInstall only this subdirectory of the cloned repo. Useful when one repo ships several themes (e.g. juicer ships all six under docs/themes/).
--forceoffOverwrite an existing theme directory. Without this, an existing <themeDir>/<name>/ aborts the install.

The metadata for an upgrade later (URL, ref, subdir) is recorded in <themeDir>/<name>/.juicer-theme.toml. Don’t commit that file is up to you — it’s small, it’s plain TOML, and committing it means collaborators get the same theme version after git pull without re-running theme add.

Note

theme add only installs the theme directory. You still have to set theme = "<name>" in site.toml to activate it — juicer doesn’t guess which of your installed themes you want active. Run juicer config -s . after editing site.toml to verify the resolved theme value.

theme upgrade

Re-fetch one or every installed theme from the URL+ref recorded in its .juicer-theme.toml. Use this after the upstream theme has shipped a fix and you want to pull it in.

sbt 'juicerJVM/run theme upgrade'
sbt 'juicerJVM/run theme upgrade juicerblog'
sbt 'juicerJVM/run theme upgrade juicerblog -r v1.3.0'
FlagDefaultWhat
<name> (positional)every themeWhich theme to upgrade. Omitted = upgrade every theme that has a .juicer-theme.toml.
-s, --source <p>.Site source directory.
-r, --ref <ref>recorded refOverride the recorded ref for this upgrade only. Doesn’t rewrite .juicer-theme.toml — the next bare theme upgrade returns to the previously-recorded value unless you also re-run theme add.

Exit codes

CodeMeaning
0Success.
1Any failure — bad source path, missing required config, parse error in site.toml, template render error, git failure in theme add/upgrade. Run with -v for the verbose stack trace.

Search

Esc
to navigate to open Esc to close