Skip to content

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

stencils:
  - type: <string>   # SOURCE × RENDER.

kind: component

stencils:
  - type: <string>   # SOURCE × RENDER.
    spec: <string>   # ── component ──

kind: include

stencils:
  - type: <string>   # SOURCE × RENDER.
    path: <string>   # ── 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"