Skip to content

rkstgr/papermake

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

92 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“„ Papermake

Content-addressable template registry with server-side rendering for Typst documents.

Turn your Typst templates into APIs. Publish once, render anywhere.

# Publish a template curl -X POST http://localhost:8080/templates/invoice/publish?tag=latest \ -F "main_typ=@invoice.typ" \ -F "schema=@schema.json" \ -F "metadata={\"name\":\"Invoice\",\"author\":\"you@company.com\"}" # Render with data β†’ PDF curl -X POST http://localhost:8080/render/invoice:latest \ -H "Content-Type: application/json" \ -d '{"company": "Acme Corp", "amount": 1500}' \ --output invoice.pdf

πŸš€ Why Papermake?

  • πŸ—οΈ Template as Code - Version your document templates like software
  • ⚑ Server-side Rendering - No local Typst installation needed
  • πŸ”’ Content-Addressable - Immutable, deduplicated storage (like Git for documents)
  • πŸ“Š Built-in Analytics - Track usage, performance, and errors
  • 🐳 Self-hostable - Deploy anywhere with Docker

πŸƒβ€β™‚οΈ Quick Start

Using Docker Compose

git clone https://github.com/rkstgr/papermake cd papermake docker-compose up -d

This starts:

  • Papermake Server on localhost:8080
  • MinIO (S3-compatible storage) on localhost:9000, inspectable at http://localhost:9001
  • ClickHouse (analytics) on localhost:8123

Manual Setup

# Copy and update .env with your S3 and Clickhouse credentials cp .env.example .env # Run the server cargo run -r -p papermake-server

πŸ“š Usage

Publishing Templates

Templates consist of:

  • main.typ - Your Typst template file
  • files: Images, fonts, other files (optional)
  • Metadata - Name, author, description
// invoice.typ // #data is automatically populated with the input data = Invoice #data.number *Bill To:* #data.customer.name *Amount:* $#data.amount
curl -X POST localhost:8080/templates/invoice/publish?tag=latest \ -F "main_typ=@invoice.typ" \ -F "files[]=@logo.png" \ -F "metadata={\"name\":\"Professional Invoice\",\"author\":\"finance@company.com\"}" # simple publish endpoint curl -X POST http://localhost:3000/api/templates/invoice/publish-simple \ -H 'Content-Type: application/json' \ -d '{  "main_typ": "#set text(font: \"Arial\")\nhello #data.name",  "metadata": {  "author": "dev@bigbank.com"  "name": "Customer Invoice",  } }'

Returns

{ "data": { "message": "Template 'invoice:latest' published successfully", "manifest_hash": "sha256:8e0e58437230ce87a69a77edec3a24412a2f656bc42456f7f87c61d5de1ad5f9", "reference": "invoice:latest" }, "message": "Template published with reference 'invoice:latest'" }

Rendering Documents

# Render to PDF curl -X POST localhost:8080/render/invoice:latest \ -H "Content-Type: application/json" \ -d '{  "number": "INV-001",  "customer": {"name": "Acme Corp"},  "amount": 1500  }' \ --output invoice.pdf

Analytics & History

# Recent renders curl localhost:8080/renders?limit=10 # Template usage stats curl localhost:8080/analytics/templates # Performance over time curl localhost:8080/analytics/duration?days=30

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Templates │───▢│ Papermake │───▢│ Registry β”‚ β”‚ (Multipart) β”‚ β”‚ Server β”‚ β”‚ (S3 + CH) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Typst Engine β”‚ β”‚ (Rendering) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 
  • Content-Addressable Storage - Templates stored by hash, deduplicated automatically
  • Immutable Versions - invoice:v1.0.0 never changes, invoice:latest is mutable
  • Render Tracking - Every render logged with input/output hashes for full auditability

πŸ› οΈ API Reference

Method Endpoint Description
POST /templates/{name}/publish?tag={tag} Upload template
GET /templates List all templates
GET /templates/{name}/tags List template versions
POST /render/{name}:{tag} Render template to PDF
GET /renders?limit=N Recent render history
GET /renders/{id}/pdf Download rendered PDF
GET /analytics/volume?days=N Render volume over time

🎯 Use Cases

  • πŸ“‘ Document Generation APIs - Invoices, contracts, reports
  • πŸ“§ Email Templates - Marketing campaigns, notifications
  • πŸ“‹ Form Processing - Applications, certificates, labels
  • πŸ“Š Report Automation - Analytics dashboards, financial reports

🀝 Contributing

git clone https://github.com/rkstgr/papermake cd papermake cargo test

Built with Rust πŸ¦€ β€’ Powered by Typst β€’ Inspired by Docker registry & Git's content addressing


Documentation (coming soon)

About

Lightning-fast and ergonomic PDF generation

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors