Craftkitdocs

Concepts

Templates, versions, variables, manifests — the mental model.

This page is the mental model behind Craftkit. Five primitives compose every workflow: templates, versions, variables, loops, and renders.

Quick Start

If you only remember one thing, remember this hierarchy:

Project
 └── Template (slug: "invoice")
      └── Template version (immutable snapshot, "v3")
           ├── Variables (manifest)
           └── Loops (repeating blocks)
                └── Render (one execution against input data)

A POST /v1/templates/invoice/render walks the chain: latest published version of invoice → manifest → validate input → enqueue render row.

Templates

A template is a visual blueprint with merge fields. It belongs to a project, has a slug (invoice, contract, ...), and accumulates versions over time.

You design templates in either the Document canvas (paginated, for contracts) or the Simple flow editor (continuous, for receipts).

Versions

Every time you click Publish version, Craftkit snapshots the template's content, compiles it, and stores it as a new immutable templateVersion. The active version is what /render uses by default. Old versions stay on disk forever — past API calls keep working.

Pin a render to a specific version:

{
  "data": { "...": "..." },
  "options": { "versionNumber": 3 }
}

Variables

A variable is a single merge field with a key, a label, a data type, and a required flag. Keys can be dot-pathed (customer.name, order.shipping.country).

Data type Description
text Single-line string
longtext Multi-line string
number Finite numeric, optional integer flag
currency Numeric with currency formatting (format: "money:EUR")
date ISO date
datetime ISO datetime
boolean True/false checkbox
image Image asset (URL or upload)
url Hyperlink
email Email address

When a version is published, Craftkit walks the template, collects every variable and loop, and stores a variable manifest on the version. That manifest is the contract behind:

  • The Zod validator that gates incoming render requests.
  • The auto-generated JSON Schema shown in the dashboard.
  • The cURL snippet on the template detail page.
  • The form fields rendered by the embeddable form route.

Loops

A loop is a repeating block (Handlebars-style {{#each items}}...{{/each}}) keyed on an array variable. Each loop has an item shape — its own list of variables. Loops are how you express invoice line items, package contents, attendee lists.

Renders

A render is one execution of one template version against one set of input data. Each render lives as a row in Postgres with:

Field Description
status queuedrenderingsucceeded | failed | cancelled
data The input payload that was validated against the manifest
downloadUrl The output asset URL once the render reaches a terminal state
durationMs Wall-clock time from enqueue to completion
source What triggered the render: api, form, partner_supplied, or dashboard
apiKeyId The API key (or embed session) that initiated the call

The dashboard's Renders tab is just a window onto this table.

Glossary

Term Meaning
Template A visual blueprint with merge fields, scoped to a project
Template version An immutable snapshot of a template's content + manifest
Variable A single merge field (key + type + required)
Loop A repeating block keyed on an array variable
Manifest The list of variables + loops extracted from a version
Render One execution of one template version against input data
API key A bearer token authenticating one project's API calls
Inbound webhook A signed URL that triggers a render from any external system
Embed session A short-lived JWT that scopes an iframe mount to one tenant + actor