Reconstruction Templates
When you run unsterwerx reconstruct, the canonical content stored in the Universal Data Set is rendered through a Tera template before being written to disk. You can swap the default template for your own to control headers, footers, frontmatter, and overall document layout.
How it works
- Unsterwerx resolves the document's temporal state (latest version, or a specific point-in-time if
--atis used). - Canonical content is read from the content-addressable store.
- The template engine loads templates from
{DATA_DIR}/templates/. - A template named
report.mdis rendered with the document's metadata as context variables. - The rendered output is either written directly (markdown) or converted to an encrypted PDF.
If no custom report.md exists in the templates directory, a built-in default is used.
Template directory
Templates live in:
~/.unsterwerx/templates/
Or under a custom data directory if you use --data-dir:
/path/to/data/templates/
This directory is created automatically during initialization. Drop a .md file there and it becomes available to the renderer.
Available variables
Every template receives these context variables:
| Variable | Type | Description |
|---|---|---|
title | string | Document filename |
document_id | string | UUID of the document |
version | integer | Canonical version number |
content_hash | string | SHA content hash |
is_signed | boolean | Whether the document carries a digital signature |
content | string | The full canonical content (denormalized from the Universal Data Set) |
generated_at | string | ISO 8601 timestamp of when reconstruction ran |
app_version | string | Current Unsterwerx version |
Writing a custom template
Templates use Tera syntax, which looks like Jinja2. Variables go in {{ double_braces }}, control flow in {% block tags %}.
Here is a minimal custom template:
# {{ title }}
{{ content }}
---
Reconstructed from document {{ document_id }} (v{{ version }}) on {{ generated_at }}.
Save this as ~/.unsterwerx/templates/report.md and every future reconstruct call will use it.
Conditional blocks
Use {% if %} to handle signed documents differently:
---
title: {{ title }}
document_id: {{ document_id }}
version: {{ version }}
generated_at: {{ generated_at }}
{% if is_signed %}signature_status: preserved{% endif %}
---
# {{ title }}
{{ content }}
{% if is_signed %}
> This document carries a digital signature. The original signature state has been preserved.
{% endif %}
---
*Reconstructed by unsterwerx v{{ app_version }} at {{ generated_at }}*
Frontmatter
YAML frontmatter at the top of a template is passed through to the markdown output, but stripped automatically when generating PDF. You can put whatever metadata you need there.
Built-in templates
Three templates ship with Unsterwerx and serve as starting points:
| Template | Purpose |
|---|---|
report.md | General-purpose reconstruction with frontmatter and signature handling |
contract.md | Contract-style layout with document ID footer |
invoice.md | Invoice-style layout with document ID footer |
The renderer always looks for report.md. The contract and invoice templates exist as reference examples you can copy and adapt. To use one of them as your default, rename it to report.md in your templates directory.
Output formats
The reconstruct command produces two formats:
Markdown
Writes the rendered template output directly. What you see in the template is what you get in the file.
The rendered markdown is converted to PDF with these characteristics:
- A4 page size (210mm x 297mm)
- Helvetica for body text, Helvetica Bold for headers
- Automatic page breaks and word wrapping
- Supports H1 through H4, ordered and unordered lists, tables, and horizontal rules
- YAML frontmatter is stripped before rendering
- RC4 encryption (V=1/R=2) prevents casual editing while allowing print and copy
Format is auto-detected from the output file extension (.md or .pdf) or forced with --format.
Signed documents
When reconstructing a signed PDF, Unsterwerx returns the original preserved PDF file rather than re-rendering through the template. This preserves the cryptographic signature chain. The template is bypassed entirely in this case.
Tips
- Keep templates simple. The content variable already holds the full document; the template just wraps it.
- Test changes with a quick
reconstructto markdown before generating PDF, since markdown renders instantly and PDF takes longer. - The template directory is watched at render time, not cached. Drop a new file in and your next
reconstructpicks it up. - If your template has a syntax error,
reconstructfails with a clear Tera parse error pointing to the line number. Fix the template and retry.