DARE Engine Documentation
Welcome to the official documentation for the DARE Engine, an AI-native, token-efficient markup language explicitly designed for generating pixel-perfect PDF documents.
Deep Introduction
DARE (Document Assembly and Rendering Engine) was born out of the need to bridge the gap between AI generation and precise document rendering. Traditional tools like HTML/CSS or LaTeX are often too verbose, unpredictable, or difficult for AI models to reliably construct into perfect PDFs without running into token limits or layout hallucinations.
DARE introduces a minimalistic, token-efficient syntax that Large Language Models (LLMs) can easily write, paired with a robust rendering engine built on top of
pdfmake. The engine compiles DARE markup directly into high-quality PDFs, ensuring that the visual output matches the AI's structural intent.
Why DARE?
- Token-Efficient: Minimalist syntax heavily reduces the token footprint, making it cheaper and faster for AI to generate complex documents.
- AI-Native: Designed specifically for LLMs. The syntax avoids deeply nested tags or complex layout calculations, which often trip up models.
- Pixel-Perfect PDF Rendering: 100% native PDF generation. What you declare is exactly what gets rendered. No HTML intermediary, ensuring consistent styling.
- Data Binding: Built-in support for injecting external JSON data directly into the document.
- Developer Friendly: Easily embeddable as a Node.js library, a CLI tool, or a REST API.
Architecture
The DARE Engine architecture consists of three main stages:
- Parser: The
module reads thesrc/parser.js
file, resolves external data (if provided), and constructs an Abstract Syntax Tree (AST) representing the document's structure and styling..dare - Compiler: The AST is transformed into a robust internal schema compatible with the underlying PDF generation library.
- Renderer: The
module takes the compiled schema and generates the final binary PDF output buffer.src/renderers/pdf.js
Anatomy of a DARE File
A standard DARE file is divided into three distinct sections, separated by
@ decorators. This separation of concerns allows for clean, readable, and maintainable documents.
1. @setup
@setupThe
@setup block defines global document settings and styling parameters. This includes page size, margins, default fonts, and global color variables.
@setup page_size: A4 margin: 40 font_family: Helvetica primary_color: #FF5733
2. @data
@dataThe
@data block is used to declare inline JSON data or map external data variables. This is incredibly useful for templating, allowing you to reuse the same .dare file for different datasets.
@data { "user": { "name": "Jane Doe", "role": "Software Engineer" }, "company": "TechCorp" }
3. @doc
@docThe
@doc block is where the actual document content and structure are declared. It uses a token-efficient markup syntax to define layout elements like containers, text blocks, images, tables, and loops, referencing the data defined in the @data block.
@doc container[width: 100%, background: primary_color]: text[size: 24, bold: true]: "Invoice for {{user.name}}" text[size: 14]: "Company: {{company}}" table[columns: 2]: row: cell: "Item" cell: "Price" row: cell: "DARE Engine License" cell: "$0.00"
DARE Components Reference
This document provides a highly comprehensive overview of all supported DARE components, including containers, text elements, media, and shapes.
Containers
Containers wrap other components and dictate their layout.
page
pageDefines a page break or a specific page context. You can style the background of a page or its margins.
- Props:
,bg
,p
,px
(for first page padding overrides).py
box
boxA versatile block container. Can be used for backgrounds, borders, or stacking content.
- Props:
,bg
,border
,borderColor
,p
,px
,py
,w
,h
(prevents page breaks inside the box).unbreakable
cols
colsA flex-like row container used to place elements side-by-side.
- Props:
(spacing between columns),gap
(number of equal-width columns),n
(space-between layout),between
(column widths).w - Usage: Automatically evenly distributes children or respects
property of children.w
creates 3 equal columns.cols(n=3)
hdr
& ftr
hdrftrPage header and footer components. Can be placed inside a
page for page-specific headers/footers, or at the root level for global headers/footers.
each
eachLoops over an array in the data context.
- Usage:
each(item in items) { txt(item.name) }
if
ifConditionally renders its content based on a truthy value in the data context.
- Usage:
if(showDetails) { txt("Details...") }
Text Elements
Elements designed for text rendering and formatting.
txt
txtStandard text block.
- Props:
(orsize
),fs
,color
,bold
,italic
,uppercase
(text-align),ta
(line-height).lh
tbl
tblCreates a table. Data is provided as semicolon-separated rows, with comma-separated cells.
- Props:
(e.g.,cols
for column widths),cols="2fr 1fr"
.unbreakable - Usage:
tbl(cols="1fr 1fr") { Header1, Header2; Row1Col1, Row1Col2 }
list
listCreates an unordered or ordered list.
- Props:
ortype="ol"
for numbered lists,type="ordered"
,size
.color
badge
badgeA small inline badge with a background color.
- Props:
,bg
,color
.size
link
linkA hyperlinked text element.
- Props:
,url
,color
.size
Media Elements
Elements for rendering images, charts, and codes.
img
imgRenders an image from a URL or local file path.
- Props:
,src
,w
,h
,center
,right
.left
bar
& pie
& line
barpielineRenders charts using the QuickChart API.
- Props:
(comma-separated),labels
(comma-separated numbers),data
,data2
,title
,color
.bg - Specifics:
for pie charts.type="donut"
qr
qrGenerates a QR code.
- Props:
,data
,w
,h
.center
Shapes & Dividers
shape
shapeDraws a geometric shape.
- Props:
(type
,rect
,triangle
),circle
,w
,h
,bg
,color
.border
hr
& line
hrlineDraws a horizontal rule/line.
- Props:
(thickness),h
.color
sp
spSpacer element to add vertical space.
- Props:
(height).h
DARE Styling Reference
This document covers all styling properties, shorthand mappings, typography, and layout flags supported by DARE.
Shorthand CSS Mappings
DARE provides an extensive set of shorthand attributes for quick and token-efficient styling.
Dimensions
: widthw
: heighth
,minw
: min-width, min-heightminh
,maxw
: max-width, max-heightmaxh
Padding & Margin
: padding (all sides)p
,pt
,pb
,pl
: padding top, bottom, left, rightpr
: padding horizontal (left/right)px
: padding vertical (top/bottom)py
: margin (all sides)m
,mt
,mb
,ml
: margin top, bottom, left, rightmr
: margin horizontalmx
: margin verticalmy
Colors & Backgrounds
: background colorbg
: text colorcolor
: border colorborderColor
Borders
: border width/styleborder
orr
: border-radiusrounded
Typography Shorthands
orsize
: font-size (automatically mapped tofs
)pt
orfont
: font-familyff
orline
: line-heightlh
: text-alignta
: text-decorationtd
: text-transformtt
: letter-spacingls
: white-spacews
: font-weightfw
Typography Flags
Boolean flags can be used directly on elements to apply typography styles instantly:
: Applies bold font-weight.bold
: Applies italic font-style.italic
: Applies underline text-decoration.underline
: Applies line-through text-decoration.strikethrough
: Transforms text to uppercase.uppercase
: Transforms text to lowercase.lowercase
: Capitalizes the first letter of each word.capitalize
Layout Flags
These boolean flags control how elements are arranged and displayed:
: Centers the element or its text. For boxes, it centers the box in its parent.center
,left
: Aligns content or the container itself to the left or right.right
: Forces a flex row layout (children side-by-side).row
: Forces a flex column layout (stack).col
: Appliesbetween
alignment for rows/columns.space-between
: Appliesaround
alignment.space-around
: Appliesevenly
alignment.space-evenly
,wrap
: Controls flex wrapping.nowrap
,stretch
,start
: Controls cross-axis alignment.end
orunbreakable
: Prevents page breaks from occurring inside the component (highly useful fornobreak
andbox
).tbl
Unit Auto-Completion
By default, numeric values for dimensions (like
w="50") are automatically appended with mm in the CSS renderer, or accurately converted to points (pt) in the PDF renderer. Certain properties (like opacity, z-index, line-height, flex) are unitless.DARE Engine Usage
The DARE Engine is highly flexible and can be integrated into your workflow in three primary ways: as a Command Line Interface (CLI), as a Node.js Library, or as a standalone REST API.
1. CLI Usage
The Command Line Interface is the easiest way to compile
.dare files into PDFs directly from your terminal.
Basic Compilation
You can run the engine using
npx (if installed globally or via package scripts) or directly via Node:
# Using npx (if configured) npx dare compile input.dare -o output.pdf # Or directly using the CLI script node cli.js input.dare output.pdf
Passing JSON Data
DARE supports data binding. You can pass an external JSON file to populate variables within your
.dare document using the --data flag.
node cli.js input.dare output.pdf --data data.json
Options:
: Show help message and usage examples.--help, -h
: Show the current version of the DARE Engine.--version, -v
2. Node.js Library
You can embed the DARE Engine directly into your Node.js applications to generate PDFs programmatically. The engine exposes two main functions:
convertFile and convertString.
Installation
Make sure to require the library in your project:
const { convertFile, convertString } = require('dare-engine');
convertFile(inputPath, outputPath, dataPath)
convertFile(inputPath, outputPath, dataPath)Reads a
.dare file from disk and saves the resulting PDF.
const path = require('path'); const { convertFile } = require('dare-engine'); async function generateInvoice() { const input = path.join(__dirname, 'invoice.dare'); const output = path.join(__dirname, 'invoice.pdf'); const data = path.join(__dirname, 'customer.json'); // Optional try { const resultPath = await convertFile(input, output, data); console.log(`PDF successfully generated at: ${resultPath}`); } catch (error) { console.error('Error generating PDF:', error); } } generateInvoice();
convertString(dareCode, options)
convertString(dareCode, options)Compiles a DARE markup string directly into a PDF buffer, useful for on-the-fly generation without touching the filesystem.
const { convertString } = require('dare-engine'); const fs = require('fs').promises; async function compileString() { const code = ` @setup page_size: A4 @doc text[size: 20]: "Hello {{name}}!" `; const options = { data: { name: "World" } }; try { const pdfBuffer = await convertString(code, options); await fs.writeFile('hello.pdf', pdfBuffer); console.log('PDF saved!'); } catch (error) { console.error(error); } } compileString();
3. REST API
The DARE Engine includes an Express-based REST API for rendering documents over HTTP. This is ideal for microservice architectures or remote rendering.
Starting the Server
Start the server locally using npm or by running the script directly:
npm start # or node server.js
The server will start on port
3000 (or process.env.PORT).
Endpoints
POST /api/render
POST /api/renderGenerates a PDF from DARE code.
Payload Format 1 (JSON): Send a JSON payload containing the
code and optional data.
curl -X POST http://localhost:3000/api/render \ -H "Content-Type: application/json" \ -d '{ "code": "@setup\npage_size: A4\n@doc\ntext: \"Hello {{name}}\"", "data": { "name": "API User" } }' \ --output result.pdf
Payload Format 2 (Plain Text): Send the DARE code directly as raw text.
curl -X POST http://localhost:3000/api/render \ -H "Content-Type: text/plain" \ -d '@setup page_size: A4 @doc text: "Hello World"' \ --output result.pdf
POST /api/preview
POST /api/preview(Legacy) This endpoint previously returned an HTML preview. In DARE v2.0, this is deprecated as the engine is now 100% native PDF. It will return a
410 Gone status indicating you should use /api/render.
GET /health
GET /healthReturns a health check status to ensure the API is running.
Deployment on Render.com
The DARE Engine is fully configured for deployment on Render.com. The repository includes a
render.yaml configuration file for a one-click Web Service deployment.
spec:render.yaml
- Type:
web - Environment:
node - Build Command:
npm install - Start Command:
node server.js - Port:
(Customizable via environment variables)10000 - Health Check:
/health
Simply connect your repository to Render, and it will automatically deploy the API server using this configuration.