- β‘ Simple. Neat. Fast. Powerful. β‘
- Perfect for creating professional, customizable PDF documents
- Leverages the most powerful PDF document generator:
$\LaTeX$ - Advanced templating with complex variables and for loops
- Persistent CLI settings and configuration management
- Built with DDD, SOLID principles, and GoF design patterns
Like, Share, Subscribe, and Hit the Bell Icon!
Please do mention the software usage in your projects, products, etc.
Built with β€οΈ by BuddhiLW. Using Bonzai π³.
go install github.com/BuddhiLW/AutoPDF/v2/cmd/autopdf@latestAutoPDF ships skills that teach a coding agent how to integrate it, so a project adopting AutoPDF does not have to feed it documentation by hand:
/plugin marketplace add BuddhiLW/AutoPDF
/plugin install autopdf@autopdf
| Skill | Covers |
|---|---|
autopdf |
Install, CLI, YAML config, choosing an integration path |
autopdf-embed |
Go library: api.Engine, testing without LaTeX, logging, v1βv2 |
autopdf-templates |
delim[[ ]] syntax, nested values, loops, escaping |
autopdf-preview |
Component documents, preview sessions, SSE/WebSocket/HTTP2 |
autopdf-plato |
Slides from Markdown/Org, Beamer, adding a render target |
They load on demand, so a project that only generates PDFs never pays for the preview documentation. See skills/ to vendor them into a single project instead.
- LaTeX PDF Generation: Professional document creation
- Template Processing: Go template syntax with custom delimiters
- YAML Configuration: Flexible and readable configuration
- Multiple Engines: Support for pdflatex, xelatex, and more
- PDF Conversion: Convert PDFs to images (PNG, JPEG, etc.)
- Complex Variables: Nested objects, arrays, and mixed data types
- For Loops: Range loops over arrays and objects
- Component Documents: Immutable semantic trees compiled into deterministic LaTeX fragments
- Live Preview Pipeline: Revisioned, cancellable previews that send changed pages only
- Persistent Settings: CLI settings that survive across sessions
- Structured Logging: Detailed logging with zap integration
- Configuration Management: Export/import configurations
- Domain-Driven Design (DDD): Clear domain boundaries
- SOLID Principles: Maintainable and extensible code
- GoF Design Patterns: Factory, Builder, Strategy, Command
- Clean Architecture: Separation of concerns
- Test-Driven Development: Comprehensive test coverage
# Simple document generation
autopdf build template.tex config.yaml
# With cleaning
autopdf build template.tex config.yaml clean
# With conversion
autopdf build template.tex config.yaml --convert png,jpeg# Complex variables with nested structures
autopdf build advanced_document.tex complex_config.yaml
# For loops with dynamic content
autopdf build loops_document.tex loops_config.yaml
# Persistent settings
autopdf verbose 3
autopdf clean on
autopdf debug switchUse pkg/api.Engine when embedding AutoPDF. It provides a context-aware,
concurrency-safe contract without requiring imports from AutoPDF internals.
engine, err := api.NewEngine()
if err != nil {
return err
}
result, err := engine.Generate(ctx, api.Request{
TemplatePath: "document.tex",
OutputPath: "output.pdf",
Variables: map[string]string{
"title": "Embedded AutoPDF",
},
})
if err != nil {
return err
}
fmt.Printf("generated %d bytes\n", len(result.PDF))Custom renderers, caching layers, and test fakes can implement api.Generator
and be installed with api.WithGenerator. See Embedding AutoPDF
for extension, logging, cancellation, and migration guidance.
For structured editors, api.DocumentEngine turns a renderer-independent
document.DocumentSpec into cached fragments and a deterministic LaTeX
projection. Production generation still returns the existing api.Result, so
adopters can add components without replacing their current PDF boundary.
Interactive sessions keep TeX auxiliary state warm, cancel superseded builds,
use focused \\includeonly builds for section components, fingerprint rendered
pages, and rasterize or transmit only changed pages. The optional HTTP adapter
adds monotonic revisions and replayable events for browser clients over either
server-sent events or WebSocket.
- Component composition and fast previews
- Streaming transports: SSE, WebSocket, HTTP/2
- Preview latency budgets and measurement
- Embedding AutoPDF
The preview adapter serves one event feed through several wire formats, so a client picks the transport that suits it without changing replay semantics:
api, _ := rest.NewPreviewAPI(rest.PreviewAPIOptions{
Engine: engine,
CompilerFactory: factory,
})
router := chi.NewRouter()
rest.RegisterPreviewRoutes(router, api)
// HTTP/2 over TLS and cleartext (h2c), with timeouts that do not
// truncate long-lived streams.
server, _ := rest.NewServer(rest.ServerOptions{Addr: ":8080", Handler: router})
server.ListenAndServe()| Route | Transport |
|---|---|
GET /sessions/{id}/events |
Server-sent events, Last-Event-ID replay |
GET /sessions/{id}/ws |
WebSocket, ?after= replay |
Both share the same cursor, history ring, and ordering. Revision submission is
bounded per session and answers 429 when the queue is saturated, so a fast
client receives backpressure instead of accumulating server-side work.
A beamer render target compiles a DocumentSpec into a PDF deck. Pair it with
plato, which parses Markdown and Org into
that spec, and one source produces both a Reveal deck and a Beamer PDF:
plato spec talk.org -o talk.json
autopdf deck talk.json talk.pdf assets=./public theme=metropolisRebuilding on every save:
autopdf deck watch talk.json talk.pdf \
watch=talk.org command="plato spec talk.org -o talk.json"AutoPDF never parses the source itself β command is a shell hook, so any front
end that emits a DocumentSpec works the same way. A render target supplies its
own catalog and an api.ManifestProjector; adding one is a new package rather
than a change to pkg/api.
template: "document.tex"
output: "output.pdf"
engine: "pdflatex"
variables:
title: "My Document"
author: "AutoPDF User"
date: "2025-01-07"template: "advanced_document.tex"
output: "advanced_output.pdf"
engine: "pdflatex"
variables:
title: "Advanced Document"
metadata:
version: "1.0.0"
tags: ["example", "advanced", "complex"]
settings:
verbose: true
debug: false
items:
- name: "Feature 1"
enabled: true
priority: 1
- name: "Feature 2"
enabled: false
priority: 2\title{delim[[.title]]}
\author{delim[[.author]]}
\date{delim[[.date]]}% Direct access to nested properties
Version: delim[[.metadata.version]]
Verbose: delim[[.metadata.settings.verbose]]
% Range loops over arrays
delim[[range .complex.metadata.tags]]
delim[[.]]\par
delim[[end]]
% Range loops over objects
delim[[range .complex.items]]
\subsection{delim[[.name]]}
Enabled: delim[[.enabled]]
Priority: delim[[.priority]]
delim[[end]]The test/ directory contains comprehensive examples:
- Simple variable substitution
- Basic YAML configuration
- LaTeX document generation
- Complex nested variables
- Range loops and dynamic content
- Mixed data types and structures
- Array iteration with
rangeloops - Object property access in loops
- Nested loop structures
- CLI settings management
- Configuration persistence
- Cross-session settings
test/model_letter/: Letter document exampletest/model_xelatex/: XeLaTeX engine exampletest/complex_variables/: Complex variable demonstration
-
Install AutoPDF:
go install github.com/BuddhiLW/AutoPDF/v2/cmd/autopdf@latest
-
Try Basic Example:
cd test/basic_usage autopdf build document.tex config.yaml -
Explore Advanced Features:
cd test/advanced_features autopdf build advanced_document.tex config.yaml -
Test For Loops:
cd test/for_loops autopdf build loops_document.tex config.yaml
# Basic build
autopdf build TEMPLATE [CONFIG]
# With options
autopdf build TEMPLATE [CONFIG] [OPTIONS]# Verbose settings
autopdf verbose [LEVEL|on|off]
# Clean settings
autopdf clean [on|off|switch|status]
# Debug settings
autopdf debug [on|off|switch]
# Force settings
autopdf force [on|off|switch]# Clean auxiliary files
autopdf clean <path>
# Convert PDF to images
autopdf convert <pdf> <formats>This project is licensed under the Apache License 2.0.

