The AI-Native PDF Language.
DARE is a high-fidelity, token-efficient markup language designed specifically for AI Agents to generate perfect PDF documents. It replaces the verbosity and unpredictability of HTML/CSS with a strict, minimalist, and deterministic system.
V2 ships with 16 built-in components, professional chart rendering, and a live web compiler.
Quick Start
The entire DARE Engine is a self-contained Node.js project. Get it running in under a minute.
1. Setup
# Clone the project repository git clone https://github.com/local-over/dare-engine.git dare-engine cd dare-engine # Install dependencies (will download a headless Chrome instance) npm install
2. Run Your First Compilation
Use the command-line tool to compile the example file.
node cli.js examples/ultimate.dare report.pdf
File Structure
A DARE file has two main blocks: @setup and @doc.
@setup { // Global settings like paper size & variables format: A4; $brand: color=#0ea5e9; } @doc { // Visual content, structured into pages page { txt($brand) { Hello World } } }
Variables ($)
Variables are the key to DARE's efficiency. Define complex styles once in @setup and reuse them with a single token.
@setup { $card: bg=#1e293b border=1 rounded=5mm p=10mm; } @doc { page { box($card) { ... } } }
Layout System
DARE's layout is powered by a simplified Flexbox and a physical unit system. This combination ensures layouts are both powerful and predictable.
Flexbox
Use display=flex on a box to arrange its
children. Combine with justify and align for
precise control.
box(display=flex, justify=space-between) { txt{Left} txt{Right} }
The Fill Command
For perfect header/footer layouts, set one box to h=fill. The engine will
automatically calculate and stretch this box to fill all remaining vertical space on the page.
page { box(h=25mm) { /* Header */ } box(h=fill) { /* Body */ } box(h=20mm) { /* Footer */ } }
Primitives
The basic building blocks of any DARE document.
| Primitive | Description |
|---|---|
page |
The root container for each page. Creates a hard boundary for content. |
box |
The fundamental container for layout and styling (like a `div`). |
txt |
The container for all text content. |
Components
DARE provides built-in "smart" components for common document needs.
| Component | Description | Example |
|---|---|---|
img |
Embeds an image. Supports local and remote URLs. | img(src="logo.png") {} |
qr |
Generates a vector QR code from a data string. | qr(data="url") {} |
bar |
Renders a high-fidelity SVG bar chart. | bar(data="A:10;B:20") {} |
tbl |
Creates a grid-based table from CSV-like data. | tbl{H1,H2; R1,R2} |
✨ V2 Components
New in DARE v2 — professional components for complete document control.
| Component | Type | Description | Example |
|---|---|---|---|
pie |
Void | SVG pie/donut chart with legend. | pie(data="A:40;B:60") {} |
badge |
Leaf | Pill-shaped status label. | badge(bg=#22c55e) { LIVE } |
list |
Leaf | Auto-formatted bullet or numbered list. | list { Item 1; Item 2 } |
link |
Leaf | Styled hyperlink with underline. | link(href="url") { Click } |
line |
Void | Horizontal rule / divider. | line(color=#e2e8f0) {} |
sp |
Void | Vertical spacer. | sp(h=10) {} |
cols |
Container | Multi-column grid layout. | cols(n=3, gap=5mm) { ... } |
hdr |
Container | Page header with flex layout. | hdr(bg=#1e293b) { ... } |
ftr |
Container | Page footer, auto-sticks to bottom. | ftr(bg=#f8fafc) { ... } |
Component Types
Container — Children are recursively parsed (page, box, cols, hdr, ftr).
Leaf — Inner content is raw text (txt, tbl, badge, list,
link).
Void — No meaningful children (img, qr, bar, pie, line, sp).
Tooling: CLI
Use the command line for local development and automated scripting. The tool is globally available in the project via `node cli.js`.
# Usage node cli.js# Example node cli.js examples/ultimate.dare report.pdf
Tooling: REST API
Start a production-ready API server for on-demand PDF generation from any application.
1. Start the Server
node server.js
2. Send a POST Request
Send your raw DARE code in the body of a POST request to /api/render.
curl -X POST http://localhost:3000/api/render \
-H "Content-Type: text/plain" \
--data-binary "@examples/ultimate.dare" \
--output api_result.pdf
Tooling: Node.js Library
Integrate the DARE engine directly into your Node.js backend for maximum control.
const dare = require('./index.js'); const fs = require('fs'); async function generate() { const dareCode = '@doc{ page{ txt{Hello} } }'; // convertString returns a PDF buffer const pdfBuffer = await dare.convertString(dareCode); fs.writeFileSync('from_lib.pdf', pdfBuffer); }
🤖 For AI Agents: System Prompt
This is the master prompt to teach any LLM how to write perfect DARE code. Use it as the system prompt or at the beginning of your conversation.
TOOL: DARE v2 PDF Engine
PURPOSE: Token-efficient markup language for AI-generated PDF documents.
STRUCTURE:
@setup { format: A4; $var: props; }
@doc { page { ... } }
UNITS: mm for layout, pt for text size. Bare numbers auto-add mm.
VARIABLES: Define in @setup with $name, reuse anywhere. Composable.
@setup { $blue: color=#0ea5e9; $title: size=24 bold $blue; }
PRIMITIVES:
page { } — Fixed page (A4/A5/Letter/Legal/A3)
box(props) { } — Container. h=fill stretches to fill remaining space
txt(props) { text } — Text content
COMPONENTS:
img(src="path") {} — Image (local file or URL)
tbl(cols="2fr 1fr") { H1,H2; R1,R2 } — Grid table. ; = row, , = cell
bar(data="A:10;B:20") {} — Bar chart (SVG)
pie(data="A:30;B:70") {} — Pie chart. type=donut for donut
qr(data="url") {} — QR code
list { Item 1; Item 2 } — Bullet list. type=num for numbered
hr {} — Horizontal divider
line(color=#ccc, thick=2) {} — Custom divider
sp(h=10) {} — Vertical spacer (10mm)
badge(bg=#e0f2fe) { TEXT } — Inline badge/pill
link(href="url") { label } — Clickable link
cols(n=3, gap=5) { } — Quick N-column grid
hdr { } — Page header (flex, spaced)
ftr { } — Page footer (flex, spaced)
CSS SHORTHANDS (saves 60%+ tokens vs HTML):
w h bg p m mt mb ml mr mx my px py pt pb pl pr
rounded/r border gap z opacity pos top bottom left right
lh(line-height) ta(text-align) td(text-decoration) tt(text-transform)
ls(letter-spacing) fw(font-weight) fs/size(font-size:pt) font/ff(font-family)
minw minh maxw maxh shadow ow ox oy
FLAGS (boolean, no value needed):
bold italic underline strikethrough uppercase lowercase capitalize
center row col wrap nowrap hidden grid inline block
between around evenly start end stretch relative absolute fixed nobreak
PATTERNS:
Header+Body+Footer:
page {
box(h=25mm, bg=#111, row, center, px=10) { txt(bold, color=white){Title} }
box(h=fill, p=15) { txt(size=12){Content} }
box(h=10mm, row, between, px=10) { txt(size=8){Left} txt(size=8){Right} }
}
Two Columns:
cols(n=2, gap=10) { box{...} box{...} }
Card:
box(bg=white, border=1, rounded=3, p=8, shadow="0 2px 8px rgba(0,0,0,0.1)") { }
RULES:
1. Always wrap content in @doc { page { } }
2. Use variables ($) for repeated styles — saves massive tokens
3. Use h=fill on the main content box
4. Use flags (bold, center, row) instead of verbose CSS
5. tbl uses ; for rows and , for columns — no nested tags
6. bar/pie data format: "Label:Value; Label:Value"
Support the Project
If DARE helps your workflow or saves you time, consider supporting its development with a coffee! Your support keeps this project alive and helps me continue improving it. Every contribution matters! 🙏
Enjoying DARE Engine?
Buy me a coffee to keep the development going!