Juicer
English

Shortcodes

Every shortcode bundled with the juicerdocs theme, with copy-pasteable examples.

Shortcodes are templates invoked from inside markdown using [= name =] syntax. The juicerdocs theme ships 16 of them, covering callouts, structured docs blocks, embeds, and inline atoms. This page is the catalogue — one entry per shortcode with the exact syntax, the rendered look, and any arguments it accepts.

Note

These are juicerdocs shortcodes. They live under docs/themes/juicerdocs/shortcodes/. If you’re using a different theme, you won’t get this set — bring your own, copy individual ones into <src>/shortcodes/, or include juicerdocs in your theme chain. See Concepts → Shortcodes for the calling conventions and how to author your own.

Tip

Escaping in this page. The code-fence examples below use [= (backslash-prefixed) so the preprocessor leaves the literal shortcode syntax in place rather than expanding it. When you write shortcodes in your own content, drop the backslash.

Callouts

Five admonition flavours, each a paired shortcode that wraps a markdown body. They share styling: a tinted background, a small icon, generous padding.

[= note =]

Neutral information. Use for “by the way” asides that the reader can skip without missing anything load-bearing.

[= note =]
The frontmatter format is YAML. JSON and TOML frontmatter are
**not** supported.
[= /note =]
Note

The frontmatter format is YAML. JSON and TOML frontmatter are not supported.

[= tip =]

A suggestion or shortcut. Use for “you can also …” content where the alternative path is sometimes the better one.

[= tip =]
The `juicer config` subcommand prints the merged config — it's
the fastest way to debug "why is this key not doing what I expect?"
[= /tip =]
Tip

The juicer config subcommand prints the merged config — it’s the fastest way to debug “why is this key not doing what I expect?”

[= warning =]

Something worth slowing down for. Use when ignoring this information will produce a confusing failure later.

[= warning =]
Permalink templates change both the URL and the on-disk write
location. Juicer doesn't keep both copies.
[= /warning =]
Warning

Permalink templates change both the URL and the on-disk write location. Juicer doesn’t keep both copies.

[= danger =]

A serious caveat. Use for “this will break things” — destructive operations, security caveats, irreversible flags.

[= danger =]
Never expose a shortcode that takes user input straight into HTML.
Run it through `markdownify` or escape it explicitly.
[= /danger =]
Danger

Never expose a shortcode that takes user input straight into HTML. Run it through markdownify or escape it explicitly.

Picking the right callout

A rule of thumb: note for information, tip for a better path, warning for a foot-gun, danger for something that will actively break.

Structured blocks

[= steps =]

Numbered, vertically-laid-out steps. Headings inside (## Step name) are auto-numbered; the body of each step is regular markdown.

[= steps =]
## Install Juicer

Clone the repo and verify with `sbt 'juicerJVM/run --help'`.

## Make a site directory

Create `site.toml`, a `content/` folder, and `layouts/_default/`.

## Build & serve

Run `sbt 'juicerJVM/run serve -s .'` and open <http://localhost:8080>.
[= /steps =]

Install Juicer

Clone the repo and verify with sbt 'juicerJVM/run --help'.

Make a site directory

Create site.toml, a content/ folder, and layouts/_default/.

Build & serve

Run sbt 'juicerJVM/run serve -s .' and open http://localhost:8080.

[= tabs =] / [= tab "Label" =]

Tabbed content panes. The outer tabs is a container; each tab takes a label as a positional arg and a markdown body.

[= tabs =]
[= tab "JVM" =]
sbt 'juicerJVM/run build -s docs'
[= /tab =]
[= tab "Native" =]
juicer build -s docs
[= /tab =]
[= /tabs =]
sbt 'juicerJVM/run build -s docs'
juicer build -s docs
node ./juicer-cli.js build -s docs

[= filetree =]

Renders the inner content in a monospace box. Use it for tree-style directory listings — box-drawing characters paste in as-is.

[= filetree =]
my-site/
├── content/
│   ├── _index.md
│   └── about.md
└── site.toml
[= /filetree =]
my-site/
├── content/
│   ├── _index.md
│   └── about.md
├── layouts/
│   └── _default/
│       ├── file.html
│       └── folder.html
└── site.toml

[= collapse "Summary" =]

Native <details> / <summary> with juicerdocs styling. The positional argument is the summary text; the body is the collapsed content (markdown is rendered inside).

[= collapse "Why no JSON frontmatter?" =]
YAML covers the use case fluently, and supporting three formats
triples the surface area to keep correct.
[= /collapse =]
Why no JSON frontmatter?

YAML covers the use case fluently, and supporting three formats triples the surface area to keep correct.

Inline atoms

Self-closing shortcodes for short, in-line UI flourishes.

[= kbd "Ctrl+K" /=]

Renders a <kbd> element styled to look like a keycap. One positional argument: the key combo to display.

Press [= kbd "Ctrl+K" /=] to focus search.
Press [= kbd "Cmd+Shift+R" /=] to hard-reload.

Press Ctrl+K to focus search. Press Cmd+Shift+R to hard-reload.

[= badge "alpha" /=]

A small pill-shaped tag. One positional argument: the text inside.

Tag your alpha pages with [= badge "alpha" /=] so readers know.
[= badge "v0.2" /=] [= badge "beta" /=] [= badge "experimental" /=]

Tag your alpha pages with alpha so readers know. v0.2 beta experimental

Buttons & calls-to-action

[= button "Label" href="..." /=] / [= buttons =]

A styled link that looks like a button. The first positional argument is the label; href is the URL; setting primary="true" swaps to the filled primary variant. Wrap one or more in [= buttons =] for an inline group.

[= buttons =]
[= button "Get started" href="/getting-started/" primary="true" /=]
[= button "Browse on GitHub" href="https://github.com/edadma/juicer" /=]
[= /buttons =]

Media

[= figure "/img/foo.png" alt="..." caption="..." /=]

A <figure> with an image and optional caption. First positional argument is the image URL. Named arguments: alt (accessibility text), caption (visible caption beneath the image).

[= figure "/img/diagram.svg" alt="Build pipeline diagram" caption="The juicer build pipeline" /=]

[= github "owner/repo" /=]

A clickable GitHub-repo card. One positional argument: the owner/repo slug. Renders the GitHub octocat icon plus the slug and the subtitle “GitHub repository”, linked to the repo.

[= github "edadma/juicer" /=]
edadma/juicer GitHub repository

[= youtube "<video-id>" /=]

A privacy-respecting iframe embed (youtube-nocookie.com). One positional argument: the YouTube video ID (the part after ?v= in the URL).

[= youtube "dQw4w9WgXcQ" /=]

Reference table

For quick lookup:

ShortcodePair / selfArgsUse for
notepairbodyAside, non-critical info
tippairbodySuggestion, shortcut
warningpairbodySlow-down, foot-gun
dangerpairbodyDestructive / serious caveat
stepspairbody w/ ## name headingsNumbered steps
tabspairone or more tab childrenTabbed content groups
tabpairargs[0] = labelOne tab inside tabs
filetreepairopaque bodyTree-style listings
collapsepairargs[0] = summary text, body = content<details> accordion
kbdself-closeargs[0] = key textKeycap styling
badgeself-closeargs[0] = label textPill / tag
buttonself-closeargs[0] = label, href, primary, iconStyled link
buttonspairone or more button childrenButton group
figureself-closeargs[0] = src, alt, captionImage with caption
githubself-closeargs[0] = owner/repoGitHub repo card
youtubeself-closeargs[0] = video IDPrivacy-friendly embed

Writing your own

Drop a template at <src>/shortcodes/<name>.html (or, in a theme, at <theme>/shortcodes/<name>.html). Inside it you have access to:

VariableWhat
.argsPositional arguments — a list of strings
.<name>Each named argument by its key
.contentThe body, if the shortcode is invoked as a pair (else absent)

A minimal callout — template at <src>/shortcodes/callout.html:

<aside class="callout callout-{{ if .kind }}{{ .kind }}{{ else }}note{{ end }}">
  {{ markdownify .content }}
</aside>

Invoke it from markdown:

[= callout kind="success" =]
The build passed.
[= /callout =]

See Concepts → Shortcodes for the full syntax (quoting rules, escaping, paired vs self-closing).

Deferred shortcodes — the [~ … ~] delimiter

The classic [= … =] syntax runs before markdown parsing. That’s the right phase for shortcodes that emit markdown — a note callout producing <aside>…</aside> flows through the markdown parser correctly because the parser sees plain HTML in the input.

What that phase can’t do is reach .page.pages, .page.subsections, .section.*, or any field of .site.* — those records don’t exist yet during the markdown pass. Trying to render a shortcode template that says {{ for p <- .page.pages }} from [= … =] silently produces an empty list.

Juicer provides a second shortcode delimiter pair, [~ … ~], that runs after the page + section + site pipeline has finished. Inside a [~ shortcode the template sees:

NamespaceWhat’s available
.page.*Full page record — title, summary, tags, pages, subsections, permalink, ancestors, prev / next, series, authors, …
.site.*Full sitedata — .site.posts, .site.pages, .site.tags, .site.authors, .site.now, .site.data, …
.args / .<key> / .contentSame as the immediate pass
\[~ section-list /~]
{{ // shortcodes/section-list.html — must be invoked from the deferred
   // pass because it depends on .page.pages and .page.subsections.   }}
{{ if .page.pages }}
  <ul>{{ for p <- .page.pages }}<li><a href="{{ p.url }}">{{ p.title }}</a></li>{{ end }}</ul>
{{ end }}
Warning

Deferred shortcodes emit HTML, not markdown. They run on the already-rendered HTML body. If your template wants to render markdown output, pipe it through \{\{ markdownify ... \}\} explicitly.

Note

Same template registry. Both delimiter pairs look up templates in shortcodes/; the difference is purely when the shortcode runs and what context it sees. A template that uses neither .page nor .site works identically from either pass.

Search

Esc
to navigate to open Esc to close