PaperStudio/Template System
UsuarioSoporteDeveloper

Template System

Docuget uses a unified template system backed by a single templates table. All templates — emails, PDFs, charts, videos — live in the same table, rendered by the same Nunjucks engine, and distinguished by two key fields:

  • source_type — determines how the template is rendered (HTML, Typst, EChart, Remotion, etc.)
  • template_category — determines what purpose the template serves (email, invoice, report, video, etc.)

This means one Templates module manages everything, with category-based filtering to keep things organized.

For the full module reference — editor UI, all Nunjucks filters, AI integration, webhooks, and caching — see Templates.

Two Template Systems

Docuget has two complementary template systems:

System Table Purpose Rendering
Templates templates Deterministic rendering (emails, PDFs, charts) Nunjucks — fast, no AI cost
AI Prompt Templates ai_prompt_template AI-powered content generation Claude API — dynamic, creative

Templates can optionally link to an AI Prompt Template via ai_template_id — for example, an invoice email template might link to an AI prompt that generates a personalized message body before the template renders the final layout.

Template Fields

Each template record has these key fields:

Field Description
template_key Unique identifier per company (e.g. calendar_event_email). Used for programmatic lookup.
template_category Purpose grouping: email, invoice, echart, video, report, system
source_type Rendering engine: html, typst, markdown, echart, remotion, etc.
content JSONB template content. Text-based templates: {"text":"..."}. Structured templates (echart, json): raw JSON object
seed_json Default values merged with caller-provided data
ai_template_id Optional link to an AI Prompt Template for content generation

Source Types

Each template has a source_type that determines how it's rendered:

Source Type Output Use Case
html HTML string Emails, web content
text Plain text Email fallback, logs
markdown HTML (via Marked) Documentation, rich content
typst PDF (via Typst compiler) Invoices, certificates, reports
json JSON string API responses, data export
xml XML string CFDI, integrations
svg SVG markup Icons, simple graphics
latex LaTeX string Academic documents
echart / echart-js SVG/PNG/PDF/HTML Charts and visualizations
tabular CSV/XLSX/JSON/HTML/Markdown Tabular data views
remotion TSX (for Remotion) Video rendering

Categories

The template_category field groups templates by business purpose:

Category Description Typical Source Type
email Email bodies (calendar, invoices, notifications) html
invoice Invoice and billing PDFs typst
echart Charts and data visualizations echart
data_science Data Science charts and tabular views echart, tabular
video Video generation pipelines remotion
report Business reports and exports typst, markdown
system System-wide shared templates (headers, footers, wrappers) varies

Categories are free-form strings — you can create new categories as needed without schema changes.

Placeholder Syntax

All template types use the same Nunjucks syntax:

Variables

{{ company_name }}
{{ invoice.total }}
{{ items[0].name }}

Conditionals

{% if discount > 0 %}
  Discount applied: {{ discount }}%
{% endif %}

Loops

{% for item in line_items %}
  {{ item.name }} — ${{ item.price }}
{% endfor %}

Filters

Filters transform values using the pipe (|) syntax:

{{ start_date | localdate }}
{{ total | money2number }}
{{ url | qrcode }}

See the Templates page for the full filter reference.

Template Lookup

Templates can be fetched two ways:

  1. By IDGET /v1/templates/:id — for direct references (e.g. invoice → template_id FK)
  2. By KeyGET /v1/templates/by-key/:key?company_id=... — for programmatic/route-based lookup (e.g. email route looks up calendar_event_email)

The template_key is unique per company, so the same key can exist in different companies with different content.

Architecture

Frontend (template_data)
    ↓
Route handler (email, invoice, video, etc.)
    ↓
template_getbykey(company_id, key)  or  template_getbyid(id)
    ↓
Merge: seed_json defaults + template_data
    ↓
templates_render(template, merged_data)
    ↓
Nunjucks renders {{ placeholders }} based on source_type
    ↓
Output delivered (email, PDF download, chart embed, etc.)

The rendering pipeline:

  1. Lookup: Template fetched by (company_id, template_key) or by ID
  2. Merge: seed_json defaults merged with provided data (caller values win)
  3. Route: source_type determines the rendering handler (Nunjucks, Marked, ECharts, etc.)
  4. Render: Template content processed with merged data
  5. Post-process: Output may be further transformed (e.g., Typst → PDF, EChart → SVG)
  6. Deliver: Final output sent to destination (email, file download, API response, video pipeline)

API Reference

Endpoint Method Description
/v1/templates GET List templates (filter by template_category, source_type, dest_type)
/v1/templates/:id GET Get template by ID
/v1/templates/by-key/:key GET Get template by key (requires company_id param)
/v1/templates POST Create template
/v1/templates/:id PUT Update template
/v1/templates/:id DELETE Delete template
/v1/templates/render/:id POST Render template with provided data