Image schemes
Standard Markdown image syntax —  — gains two custom URL schemes in the src, resolved during the transform into inline SVG:
| Syntax | Resolves to |
|---|---|
 | a generated, theme-tinted placeholder |
 | an inline icon from the theme's icon set |
 | an ordinary <img> (unchanged) |
Anything that isn't a recognised scheme — a relative path, an absolute URL, a data: URI — falls through to the normal <img> path untouched. Because the schemes resolve to an <svg> element (not an image URL), they're scalable, theme-aware, and need no network request.
placeholder:<shape> — generated placeholders
A stand-in image for drafts, fixtures, and templates: deterministic, offline, and self-contained. Pick the shape that matches the slot's aspect.
{% gallery %}



{% /gallery %}<figure data-rune="gallery" typeof="ImageGallery" data-rune-fields="{"layout":"grid","lightbox":"true"}">
<div data-name="items">
<figure data-name="item">
<svg class="rf-placeholder" data-shape="cover" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice" width="100%" fill="none" role="img" aria-label="A wide cover">
<rect x="0" y="0" width="1600" height="900" fill="var(--rf-color-surface)"></rect>
<circle cx="1216" cy="270" r="90" fill="var(--rf-color-border)"></circle>
<path d="M0 648 Q 448 495 800 630 T 1600 576 L 1600 900 L 0 900 Z" fill="var(--rf-color-muted)"></path>
<rect x="4" y="4" width="1593" height="893" fill="none" stroke="var(--rf-color-border)" stroke-width="7"></rect>
</svg>
<figcaption>A wide cover</figcaption>
</figure>
<figure data-name="item">
<svg class="rf-placeholder" data-shape="square" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMid slice" width="100%" fill="none" role="img" aria-label="A square tile">
<rect x="0" y="0" width="1000" height="1000" fill="var(--rf-color-surface)"></rect>
<circle cx="760" cy="300" r="100" fill="var(--rf-color-border)"></circle>
<path d="M0 720 Q 280 550 500 700 T 1000 640 L 1000 1000 L 0 1000 Z" fill="var(--rf-color-muted)"></path>
<rect x="4" y="4" width="992" height="992" fill="none" stroke="var(--rf-color-border)" stroke-width="8"></rect>
</svg>
<figcaption>A square tile</figcaption>
</figure>
<figure data-name="item">
<svg class="rf-placeholder" data-shape="portrait" viewBox="0 0 750 1000" preserveAspectRatio="xMidYMid slice" width="100%" fill="none" role="img" aria-label="A tall portrait">
<rect x="0" y="0" width="750" height="1000" fill="var(--rf-color-surface)"></rect>
<circle cx="570" cy="300" r="75" fill="var(--rf-color-border)"></circle>
<path d="M0 720 Q 210 550 375 700 T 750 640 L 750 1000 L 0 1000 Z" fill="var(--rf-color-muted)"></path>
<rect x="3" y="3" width="744" height="994" fill="none" stroke="var(--rf-color-border)" stroke-width="6"></rect>
</svg>
<figcaption>A tall portrait</figcaption>
</figure>
</div>
</figure><figure typeof="ImageGallery" class="rf-gallery rf-gallery--grid" data-layout="grid" data-lightbox="true" data-rune="gallery" data-density="full">
<div data-name="items" class="rf-gallery__items">
<figure data-name="item" class="rf-gallery__item">
<svg class="rf-placeholder" data-shape="cover" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice" width="100%" fill="none" role="img" aria-label="A wide cover">
<rect x="0" y="0" width="1600" height="900" fill="var(--rf-color-surface)"></rect>
<circle cx="1216" cy="270" r="90" fill="var(--rf-color-border)"></circle>
<path d="M0 648 Q 448 495 800 630 T 1600 576 L 1600 900 L 0 900 Z" fill="var(--rf-color-muted)"></path>
<rect x="4" y="4" width="1593" height="893" fill="none" stroke="var(--rf-color-border)" stroke-width="7"></rect>
</svg>
<figcaption>A wide cover</figcaption>
</figure>
<figure data-name="item" class="rf-gallery__item">
<svg class="rf-placeholder" data-shape="square" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMid slice" width="100%" fill="none" role="img" aria-label="A square tile">
<rect x="0" y="0" width="1000" height="1000" fill="var(--rf-color-surface)"></rect>
<circle cx="760" cy="300" r="100" fill="var(--rf-color-border)"></circle>
<path d="M0 720 Q 280 550 500 700 T 1000 640 L 1000 1000 L 0 1000 Z" fill="var(--rf-color-muted)"></path>
<rect x="4" y="4" width="992" height="992" fill="none" stroke="var(--rf-color-border)" stroke-width="8"></rect>
</svg>
<figcaption>A square tile</figcaption>
</figure>
<figure data-name="item" class="rf-gallery__item">
<svg class="rf-placeholder" data-shape="portrait" viewBox="0 0 750 1000" preserveAspectRatio="xMidYMid slice" width="100%" fill="none" role="img" aria-label="A tall portrait">
<rect x="0" y="0" width="750" height="1000" fill="var(--rf-color-surface)"></rect>
<circle cx="570" cy="300" r="75" fill="var(--rf-color-border)"></circle>
<path d="M0 720 Q 210 550 375 700 T 750 640 L 750 1000 L 0 1000 Z" fill="var(--rf-color-muted)"></path>
<rect x="3" y="3" width="744" height="994" fill="none" stroke="var(--rf-color-border)" stroke-width="6"></rect>
</svg>
<figcaption>A tall portrait</figcaption>
</figure>
</div>
</figure>The placeholder is a neutral scene drawn with theme tokens (--rf-color-surface / --rf-color-muted / --rf-color-border), so it picks up the active tint and dark mode automatically. Output is deterministic — the same shape always renders identically, so it's safe for screenshot tests.
Shapes
| Shape | Aspect | Use |
|---|---|---|
cover | 16:9 | hero / banner / gallery tiles |
wide | 12:5 | wide banners |
banner | 3:1 | thin page banners |
square | 1:1 | even tiles, equal-ratio media |
portrait | 3:4 | vertical cards, posters |
thumbnail | 4:3 | small previews |
avatar | round | profile / author images |
An unknown shape falls back to cover.
Drafting with placeholders lets you lay out an image-heavy page before the real assets exist, then swap each placeholder:<shape> for a real path later.
icon:<name> — inline icons
The inline shorthand for the {% icon %} rune: resolve an icon by name (e.g. icon:star, icon:mail) from the theme's icon set, right inside prose.
Give a project a  star, or reach us by  email.<p>
Give a project a
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="rf-icon" data-icon="star" role="img" aria-label="star">
<path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"></path>
</svg>
star, or reach us by
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="rf-icon" data-icon="mail" role="img" aria-label="email">
<path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path>
<rect x="2" y="4" width="20" height="16" rx="2"></rect>
</svg>
email.
</p>Give a project a star, or reach us by email.
<p>
Give a project a
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="rf-icon" data-icon="star" role="img" aria-label="star">
<path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"></path>
</svg>
star, or reach us by
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="rf-icon" data-icon="mail" role="img" aria-label="email">
<path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path>
<rect x="2" y="4" width="20" height="16" rx="2"></rect>
</svg>
email.
</p>icon:<name> draws from exactly the same icon registry as the {% icon %} rune, including group/name syntax (e.g. icon:hint/warning). Reach for the rune when you want a size override or a standalone icon; reach for icon: when an icon reads most naturally as an inline image in a sentence. An unknown name falls back to a neutral glyph.
Accessibility
The image alt becomes the accessible label:
→ the icon is exposed to assistive tech labelled "GitHub" (role="img",aria-label="GitHub").with emptyaltis treated as decorative (aria-hidden), so screen readers skip it — the right default for a stand-in image.
Write alt the same way you would for any image: describe what it conveys, or leave it empty when it's purely decorative.
A note on data:image/svg+xml
Raw inline SVG data-URIs —  — are silently dropped. The Markdown parser's link sanitiser allows data:image/png (and gif/jpeg/webp) but rejects data:image/svg+xml as an XSS-hardening measure, so the image never parses. Use placeholder: or icon: (which emit a trusted inline <svg> element, sidestepping the restriction), or a non-SVG image.
See also
- Icon — the
{% icon %}rune and the theme icon registry. - Figure · Media guests — where images land.