Template structure
A template is a set of named files plus three optional settings: a JSON Schema for its input, sample data for previews, and page settings. You edit them in the app’s editor (switch to Raw mode to see the files) or through the API.
- main.html the document body (entry file)
- styles.css any number of stylesheets
- header.html optional, repeats at the top of every page
- footer.html optional, repeats at the bottom of every page
- line-item.html a partial, used with
{{ template "line-item.html" . }}
File names carry meaning:
| File | Role |
|---|---|
main.html or index.html |
The entry file: the document body. Exactly one is required. |
*.css |
Stylesheets. They are templates too, so they can use data and functions, e.g. url({{ asset "logo" }}). Keep rules that must override each other in the same file: the order between a template’s CSS files isn’t guaranteed. |
header.html, footer.html |
A running header and footer printed on every PDF page. See Page setup. |
any other *.html |
A partial, invoked with {{ template "name.html" . }}. |
Write the body only. Doquill wraps it in the <html>, <head> and <body> elements and
injects the stylesheets, so don’t add your own document skeleton or <link> tags.
<h1>Invoice {{ .number }}</h1><table> {{ range .items }} {{ template "line-item.html" . }} {{ end }}</table><p class="total">Total: {{ currency "€" 2 .total }}</p><tr> <td>{{ .description }}</td> <td class="num">{{ currency "€" 2 .unit_price }}</td></tr>Stylesheets beyond the template’s own files
Section titled “Stylesheets beyond the template’s own files”A template also renders with workspace stylesheets attached to it:
- Built-in Tailwind, compiled from the classes your HTML uses. Premade templates have it on. See Styling & Tailwind.
- CSS assets uploaded to the workspace, either attached to this template or applied to every template in the workspace. See Images & assets.
These are injected before the template’s own CSS files, so your template’s rules win over Tailwind and shared stylesheets of equal specificity.
Draft, publish and versions
Section titled “Draft, publish and versions”Every template has one draft. Edits in the editor, and PATCH /v1/templates/{id}
calls, change the draft only.
Publishing (POST /v1/templates/{id}/publish, or Publish in the editor) copies
the draft into a new numbered version: 1, 2, 3 and so on. A version never changes after
it is published. It pins its files, schema, page settings, and the exact content of every
asset and stylesheet it uses, so a later asset upload can’t change an old document.
When you render, template_version picks what to use:
template_version |
Renders |
|---|---|
omitted or "latest" |
the most recently published version |
"3" |
version 3 |
"draft" |
the current draft, unpublished changes included |
GET /v1/templates/{id}/versions lists the published versions, and
GET /v1/templates/{id}/versions/{version} returns one with its files.
Editing through the API
Section titled “Editing through the API”PATCH /v1/templates/{id} updates the draft. Fields you leave out stay unchanged.
{ "draft": { "files": { "main.html": "<h1>Invoice {{ .number }}</h1>", "styles.css": "h1 { font-size: 20pt; }" }, "schema": { "type": "object", "required": ["number"], "properties": { "number": { "type": "string" } } }, "sample_data": { "number": "INV-1042" } }}files replaces the whole file set, so send every file, not only the changed one. The
response carries an ETag; send it back as If-Match on the next update to fail with
412 instead of overwriting someone else’s change.
An API key needs the update_template permission to edit or publish, and
create_template to create templates.