Stencils & Scribe¶
Stencils are StageFreight's reusable text elements — badges, shields, provider badges,
included fragments, inventory tables — each defined once in the top-level stencils: library
and embeddable anywhere as {id}. Scribe is the phase that places rendered stencils into
repo files (README badge rows, marked regions) and commits them back.
The stencils: library is a shared composition surface: the same {id} elements feed scribe's
file regions, and (as they land) narrate summaries and release bodies — one grammar, many
destinations. Configure stencils: + scribe: and scribe runs (presence-enabled).
stencils: — define once¶
Every renderable is declared once under the top-level stencils: key, by id. Embed it as
{id} in a scribe region (below) and it renders to markdown. Three flavors:
Inline badge (default) — a local SVG you own, drawn from your data:
stencils:
build:
label: build
message: "{env:BUILD_STATUS}"
color: auto # or a hex like "#74ecbe"
font: dejavu-sans
output: ".stagefreight/badges/build.svg"
link: "https://…/pipelines"
Inline shield (render: shield) — a shields.io badge composed from the same fields (no %2F juggling):
docker: { render: shield, label: Docker, message: "{var:org}/{var:repo}", color: "#2496ED", logo: docker, link: "https://hub.docker.com/r/{var:org}/{var:repo}" }
Named producer (type:) — an ecosystem/data producer resolved by a typed module (repo/module inferred from your repos: publish-origin; the common ones need no params):
go-report: { type: goreportcard }
contributors: { type: github-contributors }
contents-base: { type: contents, build: myapp, section: inventories.versions, render: badges }
Browse every producer type with stagefreight scribe types.
Reserved ids
A stencil id must not shadow a gitver template keyword (base, sha, version, branch,
major/minor/patch, date, …). {base} always resolves to the version fact, so a
stencil named base would be unreachable — validation rejects it.
scribe.files — place by {id}¶
scribe.files is an id → region map; each region names a file and its markers. Content
between the markers is replaced idempotently each run; everything outside them is never touched.
Fill a region one of two ways:
body: — freeform markdown with {id} stencil embeds (and {#if} conditionals). Write the
region exactly as you want it to read:
scribe:
files:
readme.hero:
file: README.md
between: ["<!-- sf:hero:start -->", "<!-- sf:hero:end -->"]
body: |
{build} {license} {release}
**{project.name}** — {project.description}
items: — sugar for a plain row of stencils (br for a row break, inline: for
side-by-side). Equivalent to a body: of space-joined {id} embeds:
readme.badges:
file: README.md
between: ["<!-- sf:badges:start -->", "<!-- sf:badges:end -->"]
inline: true # space-joined (true) | rows split on "br" (false)
items: [build, license, release, br, docker] # stencil ids (+ "br" for a break)
The stencil lives once under stencils: and is referenced by {id} — no badge_ref, no
per-file re-declaration. Any {…} the stencil engine doesn't recognize falls through to the
gitver template pass ({base}, {env:X}, {project.*}, {docker.*}, …), so version/env facts
work directly in a body: too. A link_base on the file fixes relative links and derives the
raw-content base for badge image sources.
scribe.commit — land it¶
scribe:
commit:
type: docs
message: "refresh generated docs and badges"
add: [".stagefreight/badges", "README.md"]
push: true
CLI¶
| Command | What it does |
|---|---|
stagefreight scribe apply |
Render every region and reconcile it into the marker spans (the phase, run locally). |
stagefreight scribe render <id> |
Render one stencil's markdown to stdout. |
stagefreight scribe types |
Browse stencil producer types, or detail one. |
Reference¶
stencils¶
Stencils is the shared audience-text library: id → reusable markdown element with {…} variable fill, embeddable as {id} anywhere SF composes text (scribe file regions, narrate, release bodies). Presence-neutral (a shared library, not a phase). Consumers differ only by destination.
kind: badge¶
stencils:
- type: <string> # SOURCE × RENDER.
render: <string> # form: badge (default) | shield | image | table | list | kv | versions | raw
label: <string> # ── inline badge / shield areas ──
message: <string> # right value (templates)
color: <string> # hex or "auto"
font: <string> # badge font override
font_size: <int> # badge font size override
output: <string> # SVG output path (badge generation)
link: <string> # clickable URL
logo: <string> # shields.io logo / props logo
logo_color: <string>
label_color: <string>
kind: shield¶
stencils:
- type: <string> # SOURCE × RENDER.
render: <string> # form: badge (default) | shield | image | table | list | kv | versions | raw
shield: <string> # shields.io path (render: shield)
link: <string> # clickable URL
kind: text¶
kind: component¶
kind: include¶
kind: contents¶
stencils:
- type: <string> # SOURCE × RENDER.
build: <string> # ── contents (build manifest) / ci (run-state producers) ──
source: <string>
section: <string>
columns: [<string>] # contents renderer form lives on the RENDER axis (render:), not a separate renderer: key — one…
output_file: <string>
wrap: <string>
summary: <string>
style: <string>
params: {} # ── props (github-*, goreportcard, …) ──
scribe¶
Scribe places rendered stencils into repository files and commits them: files: (placement regions whose bodies reference stencils by {id}) + commit:. Presence-enabled (files/commit gate the stage).
scribe:
store: <string> # dir for rendered file assets (default .stagefreight/scribe); path = {store}/{id}.svg
files: # id → placement region referencing stencils
- file: <string> # required
link_base: <string>
between: <value>
inline: false # items sugar: render side-by-side
items: [<string>] # stencil ids (+ "br"); sugar for a body
body: <string> # freeform markdown with {id} embeds
commit: # scribe's own auto-commit action
type: <string>
message: <string>
add: [<string>]
push: false
skip_ci: false
run_from:
allow: [<string>] # permitted origins: "primary"
mismatch: <string> # "read-only" (default), "exit", "ignore"