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.
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 a CSV-like string. | tbl{H1,H2; R1,R2} |
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 NAME: DARE PDF Language
DESCRIPTION:
A simplified, token-efficient language for defining PDF layouts. It uses a hierarchy of braces {} instead of HTML tags. It is strict and deterministic.
CORE RULES:
1. Units: Always use "mm" for layout dimensions (e.g., h=50mm). Use "pt" for text size.
2. Variables: Define styles in @setup with "$" (e.g., $style: color=red;) to save tokens.
3. Layout: The page is a fixed canvas. Use "h=fill" on the main content box to maximize space usage.
---
1. BASIC STRUCTURE (Required)
Every file must look like this:
@setup {
format: A4;
$my_style: size=12 color=#333;
}
@doc {
page {
box(h=fill, p=20mm) {
txt($my_style) { Hello World }
}
}
}
---
2. COMPONENT REFERENCE
A. Layout & Text (Use for everything)
- box(...): A container (like a div).
Attributes: w=, h=, bg=, p= (padding), m= (margin), border=, rounded=.
Flexbox: display=flex, justify=space-between, align=center.
- txt(...): Holds text.
Attributes: size=, color=, bold, italic, align=.
Example:
box(h=20mm, bg=#000, display=flex, align=center) {
txt(color=white, bold) { Title }
}
B. Images (Use if user provides an image)
- img(...): Embeds an image.
Attributes: src="path_or_url", w=, h=.
Example:
img(src="logo.png", w=30mm) {}
C. Tables (Use ONLY for structured data)
- tbl(...): A grid table.
Attributes: cols="ratio ratio", border=1.
Syntax: Do not nest tags inside. Use simple text separated by ; (rows) and , (columns).
Example:
tbl(cols="2fr 1fr 1fr") {
Item, Qty, Price;
Apple, 5, $2.00;
Banana, 10, $5.00
}
D. Charts (Use ONLY if user asks for a graph)
- bar(...): A vector bar chart.
Attributes: data="Label:Value; Label:Value", color=.
Example:
bar(data="Jan:100; Feb:250; Mar:180", color=blue) {}
E. QR Codes (Use ONLY if user asks for a link)
- qr(...): Generates a QR code.
Attributes: data="url_string", w=.
Example:
qr(data="https://google.com", w=25mm) {}
---
3. SCENARIO GUIDE
- User asks for a letter: Use "page", "box", and "txt". Do NOT use charts or tables.
- User asks for an invoice: Use "box" for layout and "tbl" for the item list.
- User asks for a dashboard: Use "bar" charts and "box(display=flex)" for columns.
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!