dct render¶
Render a dashboard to SVG, HTML, PNG, PDF, JSON, YAML, or terminal output.
Use "-" as the FACE argument to read YAML from stdin — useful for AI agents and shell pipelines that don't want to write a temp file.
Arguments¶
| Argument | Description |
|---|---|
FACE |
Path to board YAML file, or "-" to read YAML from stdin. (required) |
Options¶
| Flag | Description |
|---|---|
--output PATH |
Output file path. Default: board name with extension. Use "-" to write to stdout. |
--format TEXT |
Output format: svg, html, png, pdf, terminal, json, text, yaml, data. Default: svg. |
--project-dir PATH |
Project directory for resolving relative paths. |
--var KEY=VALUE |
Variable value (repeatable). |
--chart TEXT |
Render only this chart (by chart id). Valid only with a single board argument or stdin — rejected with multiple boards. |
--no-cache |
Bypass all query caches and re-run from scratch. |
--cache PATH |
Persist the query cache to this DuckDB file (created if absent). Default: in-memory, discarded when the process exits. Also settable via DCT_CACHE_PATH. Mutually exclusive with --no-cache. |
--diagnostics-json |
Emit all diagnostics (errors and warnings) as JSON Lines to stderr. stdout stays the render payload on success; one compact JSON object per diagnostic is written to stderr, line-delimited so a truncated read still yields whole objects. |
--allow-chart-errors |
Allow per-chart errors (missing columns, query failures, data-shape problems caught while sizing the board) without exiting non-zero. Default: fail — see Warnings & CI behavior. |
--fail-fast |
Stop immediately on the first render failure. Default: continue rendering remaining boards, exit 1 at the end. |
--max-workers INT |
Maximum parallel query workers (default: 8, from config). Also settable via DCT_MAX_WORKERS. Effective only for external warehouse executors — DuckDB serializes access internally regardless of this setting. |
--no-warnings |
Suppress warning output to stderr. Warnings still appear in --format json output so agents and consumers always see them. |
--ignore-warning CODE |
Suppress a specific render-time warning code (repeatable). Suppressed warnings move to suppressed_warnings in --format json output. A code that isn't a registered WARN-* code exits 1. |
--print0, -0 |
Delimit produced output paths with NUL (\0) instead of newline, for safe piping to xargs -0 when paths contain spaces. |
Warnings & CI behavior¶
By default, dct render exits 1 if any chart has a runtime error — a missing column, a failed query, an unresolvable reference, or a data-shape problem caught while the board is being sized (a NULL in a pie's theta column, say). This is the CI-safe contract: a broken chart fails the build instead of shipping a silently-partial dashboard.
For live previews and agent iteration, where a partial render is useful feedback rather than a failure, pass --allow-chart-errors to keep exit code 0 and render whatever charts succeeded.
Render-time warnings (as opposed to chart errors) print to stderr by default and don't affect the exit code. Use --no-warnings to silence them, or --ignore-warning CODE to suppress one specific code (repeatable):
dct docs warnings lists every registered warning code; dct docs warnings <CODE> explains one.
Output formats¶
| Format | Purpose |
|---|---|
svg (default) |
Scalable vector graphics — embedding, presentations |
html |
Interactive HTML page with embedded charts |
png |
Raster image — screenshots, thumbnails |
pdf |
PDF document — reports, printing |
terminal |
ASCII/Unicode charts printed to stdout |
json |
Post-execution resolved layout + data |
text |
Plain text rendering |
yaml |
Compiled board YAML |
data |
Flat JSON: queries keyed by name, charts keyed by slug |
Examples¶
Static export¶
dct render charts/sales.yml # → charts/sales.svg
dct render charts/sales.yml --format html
dct render charts/sales.yml --format png
dct render charts/sales.yml --format pdf
dct render charts/sales.yml --output sales.svg
Variables¶
Terminal preview¶
================================================================================
Sales Dashboard
================================================================================
Daily Revenue Trend
┌────────────────────────────────────────────────────────────┐
2400.0┤ ▗ ▟ ▗ │
2141.7┤ ▄▀▖ ▞ ▚ ▞▖ ▄▀▖ │
...
Terminal format writes directly to stdout. Use shell redirection to save:
Reading YAML from stdin¶
dct render - --format terminal --project-dir . <<'EOF'
charts:
revenue:
query:
source: ./data/sales.csv
sql: SELECT * FROM sales
type: bar
x: region
y: revenue
rows:
- revenue
EOF
There's no type: csv / file: query shape — a file is referenced with source: pointing at the path, and the table name is the file's stem (sales.csv → sales). See Inline File Sources.
echo 'charts: {revenue: {query: {source: ./data/sales.csv, sql: "SELECT * FROM sales"}, type: bar, x: region, y: revenue}}
rows: [revenue]' | dct render - --format terminal
--project-dir controls where relative file paths (CSVs, etc.) are resolved from when reading stdin. Defaults to cwd.
CI artifact generation¶
for board in charts/*.yml; do
dct render "$board" \
--format html \
--output "dist/$(basename "$board" .yml).html"
done
Inspect resolved layout for debugging¶
Extract the underlying data¶
--format data drops the layout and returns two flat maps: queries keyed by
query name, and charts keyed by slug. Each query carries its SQL and exactly
one copy of its rows; charts reference their query by name rather than
embedding the rows, so charts sharing a query do not repeat the result set.
{
"id": "sales",
"title": "Sales",
"queries": {
"monthly": {
"type": "sql",
"sql": "SELECT month, SUM(revenue) AS revenue FROM orders GROUP BY 1",
"rows": [{"month": "2026-01", "revenue": 48210}]
}
},
"charts": {
"revenue_trend": {
"type": "line",
"query": "monthly",
"title": "Revenue Trend",
"x": "month",
"y": "revenue"
}
}
}
SQL is emitted as compiled — Jinja variable references are left
uninterpolated, and the values they resolve to appear under variables. A row
cap declares itself on the affected query as
rows_truncated: {head, tail, total}; rows are never dropped silently.
Origin-absolute links in exports¶
By default, links inside rendered HTML and SVG files are root-relative
(/org/proj/d/slug/). That works when the file is served from the same host,
but breaks when it is opened as a standalone file (file://) or embedded
cross-origin.
Set public_url in your dbt_charts.yml to make export links fully-qualified:
public_url: "https://dashboards.example.com"
With that setting, dct render produces https://dashboards.example.com/d/slug/
instead of /d/slug/. Leave it unset (the default, empty string) for local use.
Caching¶
The query-result cache is in-memory by default — it lives only for the duration of the dct render process and is discarded when it exits. Pass --no-cache to skip caching entirely and force re-execution from scratch.
To persist the cache across separate dct render invocations (e.g. a script that regenerates dashboards repeatedly), pass --cache <path>:
dct render charts/sales.yml --cache cache.duckdb
dct render charts/sales.yml --cache cache.duckdb # reuses cached query results
The file is created automatically if it doesn't exist yet. --cache also reads from the DCT_CACHE_PATH environment variable, so a script can export DCT_CACHE_PATH=cache.duckdb once instead of repeating the flag. A persistent cache file supports only one writer at a time — don't point two concurrently running dct render/dct serve processes at the same file. --cache and --no-cache are mutually exclusive.
Diagnostics JSON¶
For programmatic consumers (agents, CI, IDE extensions), --diagnostics-json emits all diagnostics — both errors and warnings — as JSON Lines to stderr, leaving stdout free for the render payload:
On success, warnings stream to stderr as JSONL and the rendered output goes to stdout (or --output). On failure, errors stream to stderr as JSONL and the process exits non-zero. Each line is one compact JSON object; line-delimited format means a truncated read still yields whole diagnostics.
Related¶
dct serve— interactive preview with auto-reloaddct validate— fast pre-render validationdct query— inspect one named query without rendering the whole board