Diagram Templates
Text-defined diagrams rendered as SVG via the Pintora engine. Part of the Data Science module.
Overview
Diagram templates use the existing templates table with
source_type = "pintora". They support:
- 6 diagram types: sequence, activity, ER, class, flowchart, gantt
- Nunjucks data binding:
{{ variable }},{% for %},{% if %} $fn:data functions: pull live counts, averages, and lists from the database_formfields in seed_json: auto-generate end-user forms for data input- Short references: resolve templates via
@code - Multiple output formats: SVG, PNG, PDF, JPG, WebP
Architecture
templates table (source_type = "pintora")
├── content: Pintora DSL with {{ nunjucks }} placeholders
├── seed_json: { _form: [...fields], ...defaults, "$fn:count(table)" }
├── template_key: unique per company (e.g., "diag_api_sequence")
└── short_ref: @code auto-generated
Render pipeline: Data Resolve ($fn: + @refs) → Nunjucks Template → Pintora DSL → SVG/PNG/PDF
API Endpoints
All endpoints require JWT authentication.
Render a diagram
POST /v1/render
Content-Type: application/json
Authorization: Bearer <token>
{
"company_id": "uuid",
"template_key": "diag_api_sequence",
"output_format": "svg",
"data": {
"client": "Mobile App",
"endpoint": "/v1/orders"
},
"inline": true
}
Returns the SVG directly with Content-Type: image/svg+xml.
Get form metadata
GET /v1/render/form/diag_api_sequence?company_id=uuid
Authorization: Bearer <token>
Returns:
{
"template_id": "template_01jq5...",
"template_key": "diag_api_sequence",
"short_ref": "@k7f2n",
"description": "API Request Sequence",
"source_type": "pintora",
"form_fields": [
{
"key": "client",
"label": "Client Name",
"type": "text",
"required": true,
"default": "Browser"
},
{
"key": "endpoint",
"label": "Endpoint",
"type": "text",
"required": true,
"default": "/v1/users"
}
],
"defaults": { "client": "Browser", "endpoint": "/v1/users" },
"output_formats": ["svg", "png", "pdf", "jpg", "webp"]
}
CRUD (via templates API)
GET /v1/templates?source_type=pintora&company_id=uuid— list diagramsPOST /v1/templates— create (setsource_type: "pintora")PUT /v1/templates/:id— updateDELETE /v1/templates/:id— delete
Diagram Types
Sequence Diagram
sequenceDiagram
participant {{ client }} as Client
participant {{ server }} as Server
{{ client }} ->> {{ server }}: {{ method }} {{ endpoint }}
{{ server }} -->> {{ client }}: 200 OK
Activity Diagram
activityDiagram
start
:Receive Order;
if (Payment valid?) then
:Process Order;
else
:Reject;
endif
end
ER Diagram
erDiagram
Customer {
uuid id PK
varchar name
}
Order {
uuid id PK
uuid customer_id FK
}
Customer ||--o{ Order : "places"
Flowchart
flowchart TD
Start([Start]) --> Check{Valid?}
Check -->|Yes| Save[Save]
Check -->|No| Error[Error]
Class Diagram
classDiagram
class User {
+String name
+login()
}
Gantt Chart
gantt
title Project
dateFormat YYYY-MM-DD
section Phase 1
Task A: a, 2026-04-01, 7d
Using $fn: Data Functions
Place $fn: directives in seed_json to pull live data from the database:
{
"total_customers": "$fn:count(customers)",
"avg_invoice": "$fn:avg(invoices, amount)",
"total_orders": "$fn:count(orders)",
"_form": [
{
"key": "highlight",
"label": "Section",
"type": "select",
"options": ["all", "crm", "invoicing"]
}
]
}
Then reference in Pintora DSL:
sequenceDiagram
participant CRM as CRM ({{ total_customers }} customers)
participant INV as Invoicing (avg ${{ avg_invoice }})
Available functions: count, sum, avg, min, max, list, table,
group_count, daily_count, monthly_count.
Form System (_form convention)
The _form array in seed_json defines user-fillable fields for the
/render/:key form page:
{
"_form": [
{ "key": "name", "label": "Name", "type": "text", "required": true },
{
"key": "style",
"label": "Style",
"type": "select",
"options": ["default", "dark"]
},
{
"key": "count",
"label": "Count",
"type": "number",
"min": 1,
"max": 100,
"default": 10
},
{
"key": "show_labels",
"label": "Show Labels",
"type": "checkbox",
"default": true
}
],
"name": "Default Name",
"style": "default"
}
Field types: text, textarea, number, select, checkbox, date,
color, email, url, hidden
The _form array is metadata only — stripped before rendering. Remaining keys
are default values overridden by user input.
Frontend
- Data Science tab:
/data-science→ Diagrams tab (list + detail split panel) - Form page:
/render/:templateKey— auto-generated form from_formfields - API client:
dataScienceApi.listDiagrams(),.createDiagram(),.renderDiagram()
Conversion Matrix
| Source | Output | Engine | Priority |
|---|---|---|---|
| pintora | svg | pintora | 10 |
| pintora | png | sharp | 5 |
| pintora | sharp | 3 | |
| pintora | jpg | sharp | 3 |
| pintora | webp | sharp | 3 |
CLI
# Show form fields
docuget render diag_api_sequence --form-info
# Interactive render — prompts for each field
docuget render diag_api_sequence --interactive --out=svg --save=api.svg
# Override fields directly
docuget render diag_api_sequence --out=svg --field client=Mobile --field endpoint=/v1/orders
# Generate shareable URLs (no login required)
docuget share diag_api_sequence --ttl=86400
Debugging
Set DEBUG_RENDER=1 environment variable to enable trace logging across:
- Template handler (source_type, key, data keys)
- Render engine (converter selection, cache status)
- Pintora converter (DSL length, render timing, output size)
- Render routes (request path, template resolution)