Narrate¶
The Narrate phase composes repo-facing content — README badges, shields, and included
fragments — and commits it back. Presence-enabled: configure narrate: and it runs.
narrate: has three parts:
| Key | What it does |
|---|---|
badges |
Defines local SVG badges you own (label, value, color, font, output path, link). Rendered by stagefreight badge generate. |
patches |
For each file:, a list of items: composed into marker regions (kind: badge_ref · shield · props · text · include · component · break). |
commit |
The commit that lands the generated badges and patched files back into the repo. |
Two badge systems¶
StageFreight has two ways to put a badge in your README, and they're easy to confuse. Both are narrate item kinds and can sit on the same line:
badges + kind: badge_ref |
kind: props |
|
|---|---|---|
| What | A local SVG generator you own | A registry of external provider badges |
| Powered by | the badge package (renders SVG) |
the props package (resolver/composer) |
| Output | committed .svg files — branded, version-stamped |
markdown → an external URL with live data |
| Sources | your own data | shields.io, codecov, Go Report Card, docker-pulls, SLSA… |
| CLI | stagefreight badge generate |
stagefreight props list · props render |
| Use when | you control the data and want branded assets | you want live ecosystem data in a standard format |
In short: local badges = "I'll draw my own." props = "give me the shields.io one for docker pulls." Both compose through narrate, so they coexist happily in one README.
How it works¶
Define a badge once under badges, then reference it from a file's patches with
kind: badge_ref (or inline a one-off with kind: badge):
narrate:
badges:
- id: release
text: release # left label
value: "v{base}" # right side (template-expanded)
color: "#74ecbe" # hex, or "auto" (status-driven)
font: dejavu-sans
output: ".stagefreight/badges/release.svg"
link: "https://github.com/myorg/myrepo/releases"
patches:
- file: "README.md"
link_base: "https://github.com/myorg/myrepo/blob/main"
items:
- id: badge.release
kind: badge_ref
ref: release # → the badges[] id above
placement:
between: ["<!-- sf:badges:start -->", "<!-- sf:badges:end -->"]
mode: replace
inline: true
- id: shield.pulls
kind: shield
shield: "docker/pulls/myorg/myrepo"
link: "https://hub.docker.com/r/myorg/myrepo"
placement:
between: ["<!-- sf:badges:start -->", "<!-- sf:badges:end -->"]
mode: replace
inline: true
commit:
type: docs
message: "refresh generated badges"
add: [".stagefreight/badges", "README.md"]
Items sharing the same placement markers are composed together — inline items are space-joined, block items newline-joined.
Item kinds¶
| Kind | Purpose |
|---|---|
badge |
Inline SVG badge defined in place (label + value + color + output). |
badge_ref |
References a badge defined under narrate.badges by its ref. |
shield |
Shields.io shorthand — the path is appended to https://img.shields.io/. |
props |
An external provider badge from the props registry (see below). |
text |
Literal markdown with template variables. |
include |
Verbatim file inclusion — reads a file and inserts it as-is (used to assemble generated reference fragments into wrapper pages). |
component |
Input documentation rendered from a GitLab CI component spec. |
break |
Forces a line break between composed items. |
Placement¶
placement declares where an item's output goes, between two markers. Content between the
markers is replaced idempotently on each run; everything outside them is never touched.
placement:
between: ["<!-- sf:badges:start -->", "<!-- sf:badges:end -->"]
mode: replace # replace (default) | append | prepend | above | below
inline: true # space-joined (true) or newline-joined (false)
URL resolution¶
A file's link_base fixes relative links, and StageFreight derives a raw_base from it for
badge image sources:
| Forge | link_base |
Derived raw_base |
|---|---|---|
| GitHub | github.com/{owner}/{repo}/blob/{branch} |
raw.githubusercontent.com/{owner}/{repo}/{branch} |
| GitLab | gitlab.com/{owner}/{repo}/-/blob/{branch} |
gitlab.com/{owner}/{repo}/-/raw/{branch} |
| Gitea | {host}/{owner}/{repo}/src/branch/{branch} |
{host}/{owner}/{repo}/raw/branch/{branch} |
Absolute link values are used as-is; relative ones resolve against link_base.
Props — external provider badges¶
kind: props pulls an ecosystem-standard badge (docker-pulls, codecov, SLSA, …) from a
typed, validated resolver. params carries the provider-semantic inputs; presentation
overrides (label, link, style, logo) sit outside params.
- id: prop.pulls
kind: props
type: docker-pulls
params:
image: prplanit/stagefreight
placement:
between: ["<!-- sf:badges:start -->", "<!-- sf:badges:end -->"]
inline: true
Props resolve at narrate-run time into static markdown committed to the repo — no view-time
network calls. Unknown types and unknown/missing params are hard errors; unsupported
presentation overrides are ignored.
Discovering props
stagefreight props categories, stagefreight props list, and stagefreight props show
<type> enumerate the available prop types (docker-pulls, codecov, slsa, github-actions,
go-report-card, …) with their params and an example.
Reference¶
narrate¶
Narrate configures the Narrate phase (badges, patches, commit). Presence-enabled; dissolves the old docs:/badges:/narrator: surface. Reference docs are a kind: command build committed via narrate.commit.builds, not a subsystem here.
narrate:
badges: # Badges are SVG badge definitions rendered from build metadata (was top-level `badges.items`).…
- id: <string> # stable user-defined ID for narrator reference · required
text: <string> # left side label · required
value: <string> # right side value (templates: {env:*}, {sha}, {base}, etc.) · required
color: <string> # hex color or "auto" · required
output: <string> # SVG output path (required) · required
link: <string> # clickable URL
font: <string> # font name override
font_size: <int> # font size override
patches: # Patches are generic marked-region replacements in files (was `narrator:`): each entry names a file…
- file: <string> # File is the path to the target file (required). · required
link_base: <string> # LinkBase is the base URL for relative link rewriting.
items: [] # discriminated union by kind — see per-kind blocks below
commit: # Commit is the auto-commit action for generated output (was `docs.commit`).
type: <string> # conventional type; default: engine's
message: <string>
add: [<string>]
push: false
skip_ci: false
run_from: # gate mutation to declared origin
allow: [<string>] # permitted origins: "primary"
mismatch: <string> # "read-only" (default), "exit", "ignore"
patches items · kind: badge¶
- id: <string> # ID is the item identifier (unique within file). · required
kind: badge # Kind is the item type: badge, shield, text, component, break, include. · required
text: <string> # Text is the badge label (left side text).
value: <string> # Value is the badge value (right side text, supports templates).
color: <string> # Color is the badge color (hex or "auto").
font: <string> # Font is the badge font name override.
font_size: <int> # FontSize is the badge font size override.
output: <string> # Output is the SVG output path for badge generation.
link: <string> # Link is the clickable URL (kind: badge, shield).
placement: # Placement declares where this item goes in the target file. · required
between: <value> # Between is a two-element array: [start_marker, end_marker]. Content is placed relative to these…
after: <string> # After is a regex/literal line match (reserved for future use).
before: <string> # Before is a regex/literal line match (reserved for future use).
heading: <string> # Heading is a markdown heading match (reserved for future use).
mode: <string> # Mode controls how content is placed: replace (default), append, prepend, above, below.
inline: false # Inline renders items side-by-side when true (default: false).
patches items · kind: shield¶
- id: <string> # ID is the item identifier (unique within file). · required
kind: shield # Kind is the item type: badge, shield, text, component, break, include. · required
shield: <string> # Shield is the shields.io path (kind: shield).
link: <string> # Link is the clickable URL (kind: badge, shield).
placement: # Placement declares where this item goes in the target file. · required
between: <value> # Between is a two-element array: [start_marker, end_marker]. Content is placed relative to these…
after: <string> # After is a regex/literal line match (reserved for future use).
before: <string> # Before is a regex/literal line match (reserved for future use).
heading: <string> # Heading is a markdown heading match (reserved for future use).
mode: <string> # Mode controls how content is placed: replace (default), append, prepend, above, below.
inline: false # Inline renders items side-by-side when true (default: false).
patches items · kind: text¶
- id: <string> # ID is the item identifier (unique within file). · required
kind: text # Kind is the item type: badge, shield, text, component, break, include. · required
content: <string> # Content is raw text/markdown content (kind: text).
placement: # Placement declares where this item goes in the target file. · required
between: <value> # Between is a two-element array: [start_marker, end_marker]. Content is placed relative to these…
after: <string> # After is a regex/literal line match (reserved for future use).
before: <string> # Before is a regex/literal line match (reserved for future use).
heading: <string> # Heading is a markdown heading match (reserved for future use).
mode: <string> # Mode controls how content is placed: replace (default), append, prepend, above, below.
inline: false # Inline renders items side-by-side when true (default: false).
patches items · kind: component¶
- id: <string> # ID is the item identifier (unique within file). · required
kind: component # Kind is the item type: badge, shield, text, component, break, include. · required
spec: <string> # Spec is the component spec file path (kind: component).
placement: # Placement declares where this item goes in the target file. · required
between: <value> # Between is a two-element array: [start_marker, end_marker]. Content is placed relative to these…
after: <string> # After is a regex/literal line match (reserved for future use).
before: <string> # Before is a regex/literal line match (reserved for future use).
heading: <string> # Heading is a markdown heading match (reserved for future use).
mode: <string> # Mode controls how content is placed: replace (default), append, prepend, above, below.
inline: false # Inline renders items side-by-side when true (default: false).
patches items · kind: include¶
- id: <string> # ID is the item identifier (unique within file). · required
kind: include # Kind is the item type: badge, shield, text, component, break, include. · required
path: <string> # Path is the file path to include verbatim (kind: include).
placement: # Placement declares where this item goes in the target file. · required
between: <value> # Between is a two-element array: [start_marker, end_marker]. Content is placed relative to these…
after: <string> # After is a regex/literal line match (reserved for future use).
before: <string> # Before is a regex/literal line match (reserved for future use).
heading: <string> # Heading is a markdown heading match (reserved for future use).
mode: <string> # Mode controls how content is placed: replace (default), append, prepend, above, below.
inline: false # Inline renders items side-by-side when true (default: false).
patches items · kind: build-contents¶
- id: <string> # ID is the item identifier (unique within file). · required
kind: build-contents # Kind is the item type: badge, shield, text, component, break, include. · required
build: <string> # Build is the id of the build whose manifest this item renders (kind: build-contents). Ownership is…
source: <string> # Source is an optional path to a manifest JSON file (kind: build-contents). If omitted, uses the…
section: <string> # Section is the dot-path into the manifest (kind: build-contents). e.g., "inventories.pip"…
renderer: <string> # Renderer is the rendering format (kind: build-contents). Supported: "table", "list", "kv".
placement: # Placement declares where this item goes in the target file. · required
between: <value> # Between is a two-element array: [start_marker, end_marker]. Content is placed relative to these…
after: <string> # After is a regex/literal line match (reserved for future use).
before: <string> # Before is a regex/literal line match (reserved for future use).
heading: <string> # Heading is a markdown heading match (reserved for future use).
mode: <string> # Mode controls how content is placed: replace (default), append, prepend, above, below.
inline: false # Inline renders items side-by-side when true (default: false).
patches items · kind: break¶
- id: <string> # ID is the item identifier (unique within file). · required
kind: break # Kind is the item type: badge, shield, text, component, break, include. · required
placement: # Placement declares where this item goes in the target file. · required
between: <value> # Between is a two-element array: [start_marker, end_marker]. Content is placed relative to these…
after: <string> # After is a regex/literal line match (reserved for future use).
before: <string> # Before is a regex/literal line match (reserved for future use).
heading: <string> # Heading is a markdown heading match (reserved for future use).
mode: <string> # Mode controls how content is placed: replace (default), append, prepend, above, below.
inline: false # Inline renders items side-by-side when true (default: false).