Skip to content

Shojiku template reference ​

This page renders docs/engine/README.md.Generated here: the tables and the page index below.

View source

The complete authorable surface of the Shojiku engine, one page per feature (MDN-style): what you can write in templates.yml, what each key means, its defaults, and the diagnostics it can produce. This is the human- and machine-readable source for "what syntax exists"; keep it accurate against the code (see the curation rules in ../README.md).

These pages are on the MCP wire. An agent talking to shojiku-mcp calls list_reference for this index and get_reference — or resources/read on shojiku://reference/<page> — for a page, which answers the markdown you are reading beside that page's keys as a JSON Schema fragment. Eleven pages, this index among them, document keys the catalog names no shape for; their schema half is an empty $defs, which is itself the answer — the prose half carries those keys. Append #<key> for that key on every shape of the page carrying it. So an agent with no checkout reads the reference itself, not only the bundled examples and validate's diagnostics.

Feature availability per engine build is machine-checkable: shojiku capabilities prints the key list, and each page notes its capability keys. Template authors targeting one engine build can ignore them — they exist so GUIs/SDKs can gate features across engine versions.

The development-facing companion features.md carries the implemented-capability inventory and the decision log — that a feature exists and why it is shaped that way; the pages here carry only how to author it. It lives in the repository only and is not part of this rendered reference; the reader-facing tour of what the engine does is the site's own Features page.

A minimal template ​

yaml
page: { size: A4, margin: 25 }
sections:
  body:
    type: flow
    items:
      - type: text
        text: "Hello {customer.name}"

Full file structure (bands, bodies, styles registry): template.md.

Rendering a template ​

bash
# PDF (the core command)
shojiku render --templates templates.yml --params params.json \
  --definitions definitions.yml --output out.pdf     # --output - writes to stdout

# Static + data checks, diagnostics as JSON (definitions/params optional)
shojiku validate --templates templates.yml --params params.json

# Per-page preview PNGs ({page} is replaced by the 1-based page number)
shojiku preview --templates templates.yml --params params.json \
  --output "page-{page}.png" --scale 2.0            # 2.0 px/pt ≈ 144 dpi

# The resolved layout tree + box index as JSON (GUI/AI surface)
shojiku inspect --templates templates.yml --params params.json

# Which display variants each field type can take, and what each RENDERS
shojiku formats --templates templates.yml --lang ja-JP
#   --probe date:'yyyy年M月d日'   previews a pattern before you author it

# This build's feature keys (no inputs needed)
shojiku capabilities

Useful defaults on render / preview / inspect:

  • --lang <id> selects the locale (default: the template defaults.locale, then ja-JP); --locale-dir / --font-dir (repeatable) locate the packs, adding to $SHOJIKU_LOCALE_DIR / $SHOJIKU_FONT_DIR then ./packs/{locale,fonts}. See fonts.md.
  • --font-pack <id> (repeatable) loads a font pack in addition to the locale's own fonts.uses — how a pack made by shojiku font add is used without rewriting the locale. See fonts.md.
  • A font pack whose faces are pinned (sha256 + url:) but absent is downloaded into $SHOJIKU_CACHE_DIR before rendering; --offline refuses instead, and --font-fetch-allow <host> trusts an extra source. Rendering itself never uses the network. See fonts.md.
  • --assets-dir is what image src: paths resolve against (default: the template file's directory). Asset policy: --asset-mode open|bundled-only, --allow/deny-dynamic-image <id>.
  • Diagnostics print to stderr; validate exits non-zero on errors.

Try the bundled example:

bash
shojiku render --templates examples/business/receipt-ja/templates.yml \
  --params examples/business/receipt-ja/params.json \
  --definitions examples/business/receipt-ja/definitions.yml --output receipt.pdf
# or via the Docker image (`make docker:build` builds the local
# `shojiku-ci:local` tag; its default command renders exactly this example):
docker run --rm shojiku-ci:local > receipt.pdf
# your own files: mount them and pass normal CLI arguments
docker run --rm -v "$PWD:/work" shojiku-ci:local render \
  --templates /work/templates.yml --params /work/params.json \
  --output /work/out.pdf

Getting the binaries in the first place (source build or Docker, plus MCP-server registration for AI agents) is covered in the quickstart.

Item types ​

Every items: entry is a map with a type:. Where an item may appear depends on which part of the page holds it. A page (template.md) is made of optional bands — header and footer, repeated at the top/bottom of every page — and one body between them, which is either type: flow (items stack top-to-bottom and paginate onto new pages as they run out of room — the usual choice, flow.md) or type: absolute (every item pinned at its own box.x/box.y, single page). The placement column below uses:

  • F — in a flow body
  • A — in an absolute body
  • B — in a band (header/footer)
  • C — inside a container item, wherever that container sits
  • cell — inside a repeat cell / repeat_flow card
type:What it drawsAllowed placementPage
textstatic / interpolated / bound text; rich spans:F A B C celltext.md
rectrectangle (border/fill)F A B C cellrect.md
linestroked segment; Length endpoints (to: { x: "100%" }) or an anchor to another item (to: { item: total })F A B C cellline.md
imagePNG/JPEG/GIF/WebP/SVG assetF A B C cellimage.md
qr_codelayout-time vector QRF A B C cellqr_code.md
listone line per array entry + overflow clampF A B C celllist.md
containernestable box: origin, size, style cascadeF A B C cellcontainer.md
tablepaginating data-driven rows; a column binds a value or hosts a cell: sub-template; box: narrows it in flow or places it as one bounded block elsewhereF A B C (not cell)table.md
repeatimposition / n-up grid of data-scoped cellsF onlyrepeat.md
repeat_flowflowing card list, one card per elementF onlyrepeat_flow.md
page_breakstart a fresh pageF onlypage_break.md
char_gridmanuscript-paper / workbook character cells (+ruby)F A B C cellchar_grid.md
ellipsebox-inscribed oval, or anchor: to circle another item's glyph band; circled-option mark or decorationF A B C cellform_marks.md
checkboxalways-drawn frame + params-driven checkF A B C cellform_marks.md
page_number{page} / {pages}B onlypage_number.md

Every type in this table also takes visible:, which binds whether the item is shown to a params field — reserving its box by default, or removing it from layout with collapse: true. See visible.md.

Disallowed placements warn and skip (never a hard failure) — codes in diagnostics.md.

Concepts ​

PageCovers
template.mdfile structure: page / styles / defaults / formats / sections, bands, bodies, common item keys
defaults.mddocument presentation defaults: root style (rem root), per-type format defaults, the formats: registry
page.mdpage size, orientation, margin; the margin box as coordinate origin
document.mddocument: metadata: title / description / keywords / language / authors → the PDF's document properties (PDF only)
length.mdunits: pt, %, mm/cm/in, em/rem; round-trip; guards
box.mdbox: geometry — x/y/w/h, margin/padding, minWidth/maxWidth/minHeight/maxHeight
flex.mddefault child placement: direction, gap, alignItems, justifyContent, auto margins
grid.mdbox.type: grid — column/row tracks, fill order
flow.mdstacking, gap, pagination, what splits and what moves whole
style.mdevery style property, the cascade, named styles, box decoration
text.mdwrapping, kinsoku, textOverflow, long-text pagination
vertical_text.mdwritingMode: vertical_rl / textOrientation — vertical text (plain, spans, list, table cells, page_number)
link.mdlink: { url } hyperlinks on text/image/spans → PDF annotations
data-binding.mddata: bindings, {key:format} interpolation, bindings: named declarations, params, format types
visible.mdvisible: — show an item only for some data; the reserve-box default and the collapse: true opt-in
definitions.mddefinitions.yml: the OpenAPI-shaped schema (properties/items, format hints, constraints, display variants, params validation)
fonts.mdlocales, lang packs, valid fontFamily face ids
layout-model.mdthe resolve invariant, box tree, caps, box index
diagnostics.mdevery diagnostic code by stage

The box: keys at a glance ​

KeyMeaningPage
x yoffset from the parent origin (authoring either opts a container child out of flex)box.md
w hborder-box size; omitted = fill width / auto heightbox.md
minWidth maxWidth minHeight maxHeightCSS-order size clampsbox.md
marginouter spacing; per-side map; auto sidesbox.md
paddinginner spacing (non-negative)box.md
typechild layout mode: flex (default) | gridflex.md / grid.md
direction gap alignItems justifyContentflex keys (grid reuses some)flex.md
flexGrowchild's weighted share of leftover row widthflex.md
columns rows columnGap rowGapgrid tracks & gapsgrid.md
columnSpan rowSpangrid child's track span (≥ 1)grid.md

Style properties at a glance ​

Inherited: fontSize fontFamily fontWeight fontStyleletterSpacing lineHeight color textAlign lineBreaktextSpacingTrim hangingPunctuation writingMode textOrientationtextCombineUpright. Not inherited: verticalAlign backgroundColor borderWidthborderColor borderStyle borderRadius textOverflow overflowtextDecorationopacity. Full table with defaults and value sets: style.md.

Not supported yet ​

The cross-cutting list, gathered from the per-feature pages. Where a diagnostic reports the restriction, the entry names its code, so the claim is checkable against diagnostics.md; a structural limit that nothing reports carries a dash instead. A restriction stated here is stated on its own page's Limitations section too.

Not supportedReported as
A table inside a repeat cell, a repeat_flow card, or a table column's cell:table_in_cell
Body-cell spanning (colspan). headerGroups spans the header row onlyheader_group_span_clamped
repeat / repeat_flow / page_break outside a flow bodyrepeat_in_band, repeat_flow_in_container, page_break_in_absolute_body, …
page_number outside a bandpage_number_in_body, page_number_in_container
A text mark: in vertical writingvertical_text_unsupported
textOverflow: shrink / ellipsis on a rich spans blockspan_overflow_unsupported
Per-corner border radii; any radius on a per-side or double border, a table, or a form markborder_radius_ignored
SVG constructs outside the subset parsersvg_unsupported
Remote image sources — the render path has no network I/O, by designremote_asset_unsupported
Flex wrapping: a row is one lineflex_row_overflow
Justified text and hyphenation (textAlign is left/center/right)—
Barcode symbologies other than QR—
Arithmetic in bindings: totals and tax are computed by the host—
Per-section page geometry: one page block per document—

Reading order for new authors ​

  1. template.md — the file skeleton
  2. box.md + length.md — placing things
  3. style.md + fonts.md — making them look right
  4. flow.md + table.md — variable-length content
  5. data-binding.md — wiring in params

AI agents authoring a template end-to-end (three files → validate → preview loop) should also load the step-by-step playbook in skills/shojiku-template-author/ (AI-only — written as instructions to the agent).

Runnable examples live in the repository source (examples/ at the repo root); the snippets on each feature page are the self-contained fallback for a reader who has only these pages. An agent on the MCP wire is not such a reader — list_examples / get_example serve the full entries, the same way list_reference / get_reference serve this reference. Each example directory commits its rendered output (output.pdf + preview-<n>.png) next to the sources, so you can see what a template produces without rendering anything; make examples:render regenerates them all. The set (gallery order and one-line pitches: README.md § Gallery): examples/business/invoice-ja (a multi-page A4 invoice: paginating table with repeating header, pre-computed totals, QR + link; params-short.json renders the single-page variant), examples/business/estimate-ja (the invoice's sibling: single-rate one-pager, estimate-terms box, a negative discount row), examples/business/delivery-note-ja (a delivery note: headerGroups spanning band, data-driven row.conditionalStyles, a receipt-stamp field — partial ↔ complete delivery as two params files), examples/business/pickup-slip-ja (the Thinreports-migration worked example — the migration walkthrough's result, with the legacy .tlf + Ruby host beside it), examples/forms/application-form-ja (an A4 application form: form marks, 〒 entry cells, wareki placeholder — a blank ↔ filled-sample params pair), examples/business/event-tickets-ja (2×4 n-up event tickets with per-element QR; params-few.json = one sheet), examples/business/catalog-ja (a product catalog: repeat_flow variable-height cards, dynamic images, fit: cover), examples/business/shipping-labels-ja (2×3 n-up shipping labels: 〒 cells, list + an overflow-count line, per-order QR), examples/forms/certificate-ja (an A4 landscape certificate: double border, mincho + letter spacing, seal/medal SVGs, wareki), examples/typography/kokugo-print-ja (a kokugo worksheet: kanji practice cells + ruby, a vertical copying grid, answer cells), examples/typography/novel-ja (a B5 vertical paperback booklet: ruby-paginating vertical body, strict kinsoku + hanging punctuation, a tate-chu-yoko colophon, vertical page numbers), examples/business/restaurant-menu-us (a US Japanese-restaurant menu: English menu + USD prices with vertical Japanese accents — writingMode: vertical_rl brand column + per-dish dish names, double border, mincho), examples/business/invoice-en (Letter US-style invoice: USD cents, plural-aware quantities, Net-30 terms block), examples/forms/certificate-en (Letter-landscape certificate: real italics, en-US dates), examples/business/receipt-ja (an A4 receipt: containers, %, named styles), examples/business/receipt-us (80mm thermal, custom page size), examples/business/receipt-zh-tw / examples/business/receipt-zh-cn (the same receipt geometry under zh locale packs), examples/business/receipt-hi-in (Devanagari conjuncts + lakh/crore digit grouping) / examples/business/receipt-fil-ph (Latin face + the Philippine peso) / examples/business/receipt-th-th (Thai wrapped at word boundaries, dated in the Buddhist era), examples/typography/genkoyoshi-ja (a B5 vertical 200-cell genkoyoshi: char_grid + aozora ruby) and its horizontal twin examples/typography/genkoyoshi-yoko-ja, examples/forms/rirekisho-ja (an A3 landscape JIS-style rirekisho: custom page size, 2-column header, full-width tables), and examples/dev/layout-showcase — the component-showcase document (rich spans, hyperlinks, flex/grid, overflow policies, zebra table, list, QR, SVG gradient, repeat_flow, repeat imposition starting in place with trim guides and a document-scoped cell value (breakBefore: auto, cutMarks, scope: document), page_break), one labeled section per feature family, each demo followed by a code panel showing the YAML that produces it. The showcase is the visual index of the engine, Bootstrap-docs style: its rendered pages show the look and the syntax side by side; open the feature's reference page for the full key table. It grows with the engine — every new authorable feature adds a showcase section (demo + code panel) in the cycle that ships it.

Every page ​

PageCovers
box — position, size, spacing, boundsPosition, size, margin, padding and min/max bounds — the border-box every item is placed by.
char_grid — manuscript-paper / workbook / form character cellsOne character per cell: manuscript paper, practice sheets, and form entry boxes.
type: containerAn origin and a resolved size: children position, resolve %, and inherit against it.
Data binding & formattingHow templates bind runtime params and how the locale pack formats them for display.
Template defaults & the format registryDocument-wide presentation defaults and the named format registry — the CSS :root analog.
definitions.yml — the data dictionaryThe data dictionary: the engineer-to-author seam that enriches validation and formatting.
Diagnostics referenceThe complete registry of every code the engine can emit, with severity and meaning.
document: — document metadataDocument metadata written into the PDF's properties: title, description, keywords, language, authors.
Flex layout (box.type: flex, the default)The default container mode: CSS-flex semantics down to the defaults, keyed on box.type.
Flow — stacking & paginationA flow body stacks items top-down and paginates when content passes the region bottom.
Locales & fonts (packs)Locale packs and font packs: where formatting data and typefaces come from.
type: ellipse / type: checkbox — form marksChoice marks drawn as vector paths — circling a printed option, or a checkbox.
Static grid (box.type: grid)Explicit column tracks — fr weights and auto sizing — instead of a flex stack.
type: imageA raster or SVG image from a template-time source or a params-bound value.
The layout modelHow a template plus params becomes the resolved layout tree every backend draws.
Lengths & unitsEvery geometry value: absolute units, %, em/rem, and where each has no basis.
type: lineA stroked segment between two points — no box, its own style shape.
link: — hyperlinksA clickable URL emitted as a PDF link annotation over the item's drawn geometry.
type: listA bounded per-element list: one entry per line, clamped with an overflow line.
page — size, orientation, marginSheet geometry: paper size, orientation, and the margin box every coordinate resolves against.
type: page_breakAn explicit break: the next flow item starts on a fresh page.
type: page_numberThe current page number — band-only, because the count is known at assembly.
type: qr_codeA QR code encoded at layout time into vector modules — static text or a bound value.
type: rectA rectangle: pure decoration painted by the unified style properties.
type: repeat — imposition / n-upImposition / n-up: N data-scoped copies of one cell laid onto each page.
type: repeat_flow — flow repeat (card list)One auto-height card per array element, in normal flow — a vertical card list.
style — appearance properties & the cascadeEvery appearance property and the three-surface cascade that resolves them per item.
type: tableA data-driven table: bound or container columns, spanning headers, conditional rows, row-by-row pagination.
Template file structureThe file's own shape: top-level keys, the header/body/footer sections, and what every item shares.
type: textStatic, interpolated, or bound text — inline spans, ruby, wrapping, and overflow.
Vertical writingVertical writing: characters fill a column top-to-bottom, columns lay out right-to-left.
visible: — show an item only for some dataShow an item only for some data: the form-mark presence predicate on any item, reserving its box or removing it from layout.