CLI tool to generate PDF documents from .pen files — a JSON-based design format.
- Full layout engine — Flexbox-like layout with
vertical/horizontalstacking,gap,padding,justifyContent,alignItems, andfill_containerresponsive sizing - Typography — Font embedding with
fontFamily,fontSize,fontWeight,fontStyle,letterSpacing,lineHeight, andtextAlign - Auto-sizing — Frames without explicit dimensions automatically size to fit their content
- Design variables — Reusable
$variabletokens for colors, fonts, spacing, and sizes - Image fills — Background images with cover mode, clipping, and configurable opacity
- Rounded corners — Frames with
cornerRadiusand solid or image backgrounds - Multi-page — Each top-level frame becomes a separate PDF page
- Auto font download — Missing fonts are detected and downloaded from Google Fonts with a single prompt
- Fallback fonts — Embedded Go fonts as fallback when fonts are unavailable
Download the latest pre-compiled binary for your platform from the Releases page.
# Linux (amd64)
curl -Lo pen2pdf https://github.com/vpedrosa/pen2pdf/releases/latest/download/pen2pdf-linux-amd64
chmod +x pen2pdf
sudo mv pen2pdf /usr/local/bin/
# macOS (Apple Silicon)
curl -Lo pen2pdf https://github.com/vpedrosa/pen2pdf/releases/latest/download/pen2pdf-darwin-arm64
chmod +x pen2pdf
sudo mv pen2pdf /usr/local/bin/
# macOS (Intel)
curl -Lo pen2pdf https://github.com/vpedrosa/pen2pdf/releases/latest/download/pen2pdf-darwin-amd64
chmod +x pen2pdf
sudo mv pen2pdf /usr/local/bin/Requires Go 1.21+.
go install github.com/vpedrosa/pen2pdf@latestgit clone https://github.com/vpedrosa/pen2pdf.git
cd pen2pdf
go build -o pen2pdf .pen2pdf render input.pen -o output.pdfOn first run, pen2pdf detects missing fonts and offers to download them from Google Fonts:
Missing 15 font(s):
- Inter 700
- Montserrat 300
...
Download from Google Fonts to ./fonts? [Y/n] y
downloaded: Inter-Bold.ttf
downloaded: Montserrat-Light.ttf
...
15 font(s) downloaded to ./fonts
PDF written to output.pdf (2 pages)
Downloaded fonts are saved next to the .pen file in a fonts/ directory and reused on subsequent runs.
pen2pdf render input.pen --pages "Travel Flyer"pen2pdf render input.pen --no-promptSkips the font download prompt and uses fallback fonts. Useful for CI/CD pipelines.
pen2pdf validate input.penChecks that the file parses and variables resolve correctly, without rendering.
pen2pdf info input.penDisplays pages, variables, and fonts used in the document.
.pen files can be created and edited visually with Pencil.
A .pen file is a JSON document describing a tree of visual nodes:
frame— Container with optional fill (solid color or image), corner radius, clipping, and layout propertiestext— Text node with full typography control
{
"version": "2.7",
"children": [
{
"type": "frame",
"id": "page1",
"name": "My Page",
"width": 800,
"height": 1000,
"fill": "#FFFFFF",
"layout": "vertical",
"gap": 20,
"padding": 40,
"justifyContent": "center",
"alignItems": "center",
"children": [
{
"type": "text",
"id": "title",
"name": "title",
"content": "Hello World",
"fill": "$primary-color",
"fontFamily": "Inter",
"fontSize": 48,
"fontWeight": "700"
}
]
}
],
"variables": {
"primary-color": { "type": "color", "value": "#FF6B35" }
}
}task # lint + test + build
task test # go test with race detector and coverage
task build # build to ./bin/pen2pdf
task lint # golangci-lint
task fmt # format code
task dev # start Air hot-reload
task clean # remove build artifactsMIT License. See LICENSE for details.