PDF generation is no longer a background job.
Sub-8ms dynamic PDF/A documents powered by native Typst. Universal document engine for SaaS invoices, executive reports, and payment receipts. No Headless Chrome. No Chromium bloat.
Try Interactive Web Playground & Cost Calculator (rubrol.com)
Typst is a compiler. You give it a .typ file, it gives you a PDF. What Rubrol adds on top:
- REST API + process isolation - concurrent requests, hot-reload templates,
POST /v1/renderfrom any language without managing subprocesses or file I/O yourself - Template management - store, version, and serve templates via API; no filesystem juggling per deployment
- Factur-X / EN 16931 pipeline - XMP metadata injection,
/AFRelationshipPDF dictionary, Schematron validation; skip the 2-3 months to get EU e-invoicing compliance right - One Docker image -
docker run ghcr.io/maxcomperatore/rubrol:GAand you have a production-ready PDF service in 2 minutes - 8 client SDKs - drop-in libraries for Python, Node, Go, Ruby, PHP, Java, .NET, Rust
If you are generating one PDF type internally, raw Typst is fine. If you need a multi-tenant PDF service or legally compliant EU invoices at volume, that is what Rubrol saves you from building.
Every engineering team has built the same accidental infrastructure:
User clicks "Download Invoice"
[1] API enqueues task into Redis / BullMQ / Celery / SQS
[2] Heavy Headless Chrome container spins up (1.5 GB RAM, 2,500ms cold start)
[3] PDF uploaded to S3 bucket / blob storage
[4] Polling endpoint or email webhook notifies user: "Your invoice is ready"
Because Chromium was slow, memory-leaking, and prone to OOM crashes, we were forced to treat document generation as an asynchronous queue problem.
Rubrol changes the physics:
- 5.8ms Compilation Latency: Faster than a SQLite query or Redis read.
- < 28MB Resident RAM: Zero Chrome browser processes, zero zombie renderer leaks.
- Synchronous HTTP Streaming: Render and return binary
application/pdfdirectly in your request/response cycle.
User clicks "Download Invoice"
[1] API makes local call to Rubrol Sidecar (< 6ms)
[2] Instant binary PDF stream returned to user (< 15ms total round-trip)
Delete your Redis queues, Celery workers, BullMQ listeners, and S3 polling loops. With Rubrol, document generation is now an instantaneous synchronous HTTP response.
Adopting Rubrol is not just about replacing a rendering library; it fundamentally changes the operational profile of your engineering team:
| Legacy Document Stack | With Rubrol Native Engine | The Architectural Superpower |
|---|---|---|
| The Queue Janitor | The Systems Simplifier | You walk into architectural review having deleted your Redis queues, Celery worker fleet, and S3 polling loops. |
| The Midnight Pager Victim | The Undisturbed Sleeper | When monthly billing compiles 100,000 invoices concurrently, your cluster hums at 28MB RAM with zero OOM crashes. |
| The Spinner Apologist | The Sub-15ms Speed Demon | Users click "Download" and the PDF is on their desktop in 15ms. No loading spinners, no delayed emails, no expired links. |
| The CSS Print Sufferer | The Typographic Master | You never touch brittle @media print CSS hacks again. You write clean, deterministic Typst templates that compile cleanly. |
| The Compliance Panicker | The Enterprise Hero | When leadership worries about the 2026 EU EN 16931 e-invoicing mandate, you deliver turnkey Factur-X / PDF/A-3b in one endpoint. |
- You Delete an Entire Distributed Tier: Collapsing an asynchronous 4-hop architecture (API → Redis → Chromium Worker → S3 → User) into a single synchronous 6ms HTTP response makes your system dramatically easier to reason about, test, and deploy.
- You Become Immune to Out-Of-Memory Outages: Chromium memory leaks are the #1 cause of PDF cluster evictions. Rubrol's stateless, sub-28MB memory ceiling means you can handle 1,200+ requests per second on a single modest container without breaking a sweat.
- You Make Your Application Feel Like Desktop Software: In an era where web apps feel increasingly sluggish with spinners and polling modals, delivering a 77KB production invoice in 15 milliseconds creates an unforgettable, desktop-grade user experience.
- You Conquer European Regulatory Mandates in 5 Minutes: Instead of spending 6 months building XML parsers, XMP metadata injection, and Schematron validators for France and Germany, you drop in
POST /v1/facturx/renderand hand compliant invoices to corporate customers on day one.
- Why not just use Typst directly?
- The Architecture Shift: Eliminating Background Queues
- The Architectural Transformation: Developer Superpowers
- The Problem & The Solution
- Performance Benchmarks
- Use AI to Integrate Rubrol
- Getting Started in 30 Seconds
- HTTP Sidecar API Reference
- Multi-Language Client Examples
- Precompiled Sample Output PDFs
- Template Authoring Guide
- EU Factur-X & ZUGFeRD Turnkey Suite (EN 16931)
- Production Deployment
- Commercial Licensing & Sidekiq Dual-License Model
- Commercial Licensing FAQ
- Contributing Guidelines
- Technical FAQ & Troubleshooting
-
The Villain: Headless Chrome, Puppeteer, and Playwright consume 1.5GB to 2GB of RAM per process, suffer cold starts
$>1,500\text{ms}$ , and frequently trigger Out-Of-Memory (OOM) crashes across Kubernetes clusters during batch billing runs. - The Legacy Trap: Monolithic HTML-to-PDF renderers (WeasyPrint, Gotenberg, wkhtmltopdf) suffer from brittle CSS Paged Media pagination, broken table page breaks, and complex foreign library dependencies.
-
The Solution (Rubrol): 100% Open Source GNU LGPLv3 core engine with commercial licensing (Sidekiq model). Compiles documents using native Typst in
$< 8\text{ms}$ with$< 28\text{MB}$ RAM, running as a stateless universal HTTP sidecar next to any backend service.
Rubrol includes a built-in benchmark runner so you can verify sub-millisecond compilation latencies directly on your own hardware.
# Run 50 warm-cache iterations on the standard B2B SaaS invoice
python rubrol.py benchmark
# Or benchmark specific templates with custom iterations
python rubrol.py benchmark -t facturx_invoice -n 100
# Output raw JSON metrics for CI/CD pipelines
python rubrol.py benchmark --json============================================================================
RUBROL SUB-MILLISECOND ENGINE BENCHMARK
============================================================================
Document Template: b2b_invoice (Standard 2-Page SaaS Invoice)
Sample Output : 77,692 bytes (PDF/A compliant)
Test Runs : 50 iterations (Warm cache)
----------------------------------------------------------------------------
LATENCY DISTRIBUTION (Compilation Time):
Min Latency : 5.44 ms
P50 (Median) : 5.52 ms
P90 Latency : 5.66 ms
P95 Latency : 5.71 ms
P99 Latency : 6.03 ms
Max Latency : 6.15 ms
Throughput : 181.4 docs / sec (Single vCPU core)
----------------------------------------------------------------------------
SPEED COMPARISON (Compilation Latency - Lower is better):
Headless Chrome (Puppeteer) : [========================================] 1,850.0 ms
Gotenberg (Go + Chromium) : [============== ] 650.0 ms
WeasyPrint (Python + Cairo) : [========== ] 480.0 ms
Rubrol (Native Typst Core) : [= ] 5.5 ms (336x faster)
----------------------------------------------------------------------------
[PASS] Synchronous HTTP generation SLA verified (5.52ms < 10ms).
Document generation can run synchronously inline. No background worker needed.
============================================================================
Tested on an AWS EC2 c6i.xlarge instance (4 vCPU, 8GB RAM), compiling standard 2-page B2B SaaS invoices:
| Metric | Headless Chrome / Puppeteer | Gotenberg (Go + Chromium) | WeasyPrint (Python + Cairo) | Rubrol Engine (Native Typst) |
|---|---|---|---|---|
| P50 Compilation Latency | 1,850 ms | 650 ms | 480 ms | 5.5 ms (336x faster) |
| P99 Compilation Latency | 3,400 ms | 1,150 ms | 920 ms | 6.0 ms |
| RAM Footprint (Resident RSS) | 1,600 MB | 480 MB | 160 MB | < 28 MB (57x less memory) |
| Throughput (1 vCPU Core) | ~0.5 docs/sec | ~1.5 docs/sec | ~2.1 docs/sec | > 180 docs/sec |
| Cold-Start Penalty | 2,500 ms - 3,200 ms | 800 ms - 1,200 ms | 400 ms | < 8 ms |
| Concurrency Ceiling (1 Pod) | ~40 req/s (OOM risk) | ~120 req/s | ~80 req/s | > 1,200 req/s |
| PDF Archival Standard | Manual / Brittle scripts | Manual / Incomplete | Incomplete | Native ISO 19005-3 & ISO 19005-2 |
| Turnkey EU Factur-X (EN 16931) | None | Third-party glue | Third-party glue | Built-in Native Module |
If you use an AI coding assistant like Cursor, Claude Code, or GitHub Copilot, you can add Rubrol sub-millisecond PDF generation to your application in minutes using agent skills or cursor rules.
|
Compatible with Claude Code, GitHub Copilot CLI, Amp, Codex, and open agents npx skills add maxcomperatore/rubrol --skill rubrol |
Compatible with Cursor, Windsurf, Roo Code, and VS Code Copilot curl -fsSL https://raw.githubusercontent.com/maxcomperatore/rubrol/main/.cursorrules > .cursorrules |
Once installed, simply prompt your AI coding assistant with instructions like:
"Add Rubrol PDF invoice generation to my Express / FastAPI / Next.js backend with sub-millisecond latency and dynamic line items."
- Container Orchestration: Adds Rubrol (
ghcr.io/maxcomperatore/rubrol:latest) to yourdocker-compose.ymlor Kubernetes deployment manifests. - Dynamic Typst Templates: Generates clean
.typdocument templates with native#tablelayouts, headers, and footers driven bysys.inputs. - HTTP Client Integration: Injects zero-dependency API calls to
POST /v1/renderorPOST /v1/facturx/renderreturning binary PDF streams directly to your users.
pip install typst pypdfpython rubrol/core/server.py --port 8080Open http://localhost:8080 in your browser to inspect the real-time split-pane editor, interactive SVG preview, and Puppeteer cost calculator.
python rubrol.py compile \
--template rubrol/templates/b2b_invoice.typ \
--data rubrol/data/b2b_invoice.json \
--output invoice.pdf \
--standard a-2bcurl -X POST http://localhost:8080/v1/render \
-H "Content-Type: application/json" \
-d '{
"template": "b2b_invoice",
"data": {
"invoice_number": "INV-2026-0042",
"total": 2500.00
},
"pdf_standard": "a-2b"
}' --output invoice.pdfThe Rubrol HTTP sidecar listens on port 8080 by default and responds with binary documents, real-time telemetry headers, and strict JSON error bodies.
| Method | Endpoint | Description | Input | Output |
|---|---|---|---|---|
POST |
/v1/render |
Render pre-registered template with JSON data | JSON Body | application/pdf (or image/svg+xml) |
POST |
/v1/render/raw |
Compile arbitrary Typst markup on the fly | JSON Body | application/pdf (or image/svg+xml) |
GET |
/v1/templates |
List all discovered templates in registry | None | application/json |
GET |
/health |
Liveness & readiness probe | None | application/json |
GET |
/api/sample-data |
Retrieve sample payload for a template | Query ?template= |
application/json |
| Method | Endpoint | Description | Input | Output |
|---|---|---|---|---|
POST |
/v1/facturx/render |
Generate hybrid PDF/A-3b + EN 16931 XML invoice | JSON Body | application/pdf |
POST |
/v1/facturx/validate |
Validate compliance of a PDF or JSON payload | Binary PDF / JSON | JSON Diagnostic Report |
POST |
/v1/facturx/extract |
Extract embedded factur-x.xml from PDF |
Binary PDF | text/xml |
Renders a named template from the template registry using dynamic JSON variables.
Content-Type: application/json{
"template": "b2b_invoice",
"data": {
"invoice_number": "INV-2026-9921",
"currency_symbol": "$",
"total": 1800.00,
"line_items": [
{
"description": "Rubrol Pro Annual Commercial License",
"qty": 1,
"unit_price": 1800.00
}
]
},
"format": "pdf",
"pdf_standard": "a-2b"
}template(string, required): Name of the template (stem of.typfile, e.g."b2b_invoice","saas_receipt").data(object, optional): Arbitrary nested dictionary passed directly into the template as JSON.format(string, optional, default:"pdf"): Output format:"pdf","svg", or"png".pdf_standard(string, optional, default:"a-2b"): PDF/A standard profile:"a-2b","a-3b","1.7", or"none".
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="document.pdf"
Content-Length: 74438
X-Render-Time-Ms: 6.42
Access-Control-Allow-Origin: *Compiles arbitrary Typst source code provided dynamically in the request payload.
{
"template_src": "= Hello Rubrol\\nThis document was generated in #sys.inputs.at(\\\"speed\\\", default: \\\"5ms\\\").",
"data": {
"speed": "6.1ms"
},
"format": "pdf",
"pdf_standard": "a-2b"
}Lists all .typ templates currently registered in the engine.
{
"templates": [
"b2b_invoice",
"saas_receipt"
]
}Kubernetes readiness & liveness probe returning server health, loaded templates, and Factur-X engine status.
{
"status": "healthy",
"service": "rubrol-engine",
"version": "1.0.0",
"templates_loaded": 2,
"cached_compilers": 1,
"facturx_suite": true,
"facturx_version": "1.0.07 / ZUGFeRD 2.2 (EN 16931)"
}Generates a fully compliant, legal Factur-X / ZUGFeRD 2.2 hybrid electronic invoice compliant with European Standard EN 16931. It compiles a visual PDF/A-3b document, validates the accounting calculations, generates the UN/CEFACT CII XML stream (factur-x.xml), and embeds it into the PDF container with /AFRelationship /Alternative metadata.
{
"template": "b2b_invoice",
"profile": "EN 16931",
"data": {
"invoice_number": "FA-2026-0042",
"issued_date": "2026-09-17",
"seller": {
"name": "Rubrol Solutions SAS",
"vat_id": "FR12345678901",
"country": "FR"
},
"buyer": {
"name": "Deutsche Cloud GmbH",
"vat_id": "DE987654321",
"country": "DE"
},
"currency": "EUR",
"line_items": [
{
"line_id": 1,
"name": "Rubrol Enterprise License",
"qty": 1,
"unit_price": 1000.00,
"tax_rate": 0.20
}
],
"grand_total": 1200.00
}
}HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="factur-x-invoice.pdf"
X-FacturX-Profile: EN 16931
X-FacturX-XML-Bytes: 6040
X-Render-Time-Ms: 16.80Validates any binary PDF or JSON payload against EN 16931 and Factur-X specifications.
- Binary PDF Input (
Content-Type: application/pdf): Inspects XMP metadata,/EmbeddedFilesname tree,/AFdictionary relationships, and XML syntax. - JSON Input (
Content-Type: application/json): Validates seller/buyer tax identifiers, arithmetic totals, and currency codes.
{
"valid": true,
"embedded_xml_found": true,
"af_relationship_valid": true,
"xmp_metadata_valid": true,
"conformance_level": "EN 16931",
"invoice_number": "FA-2026-0042",
"grand_total": "1200.00",
"currency": "EUR",
"xml_bytes": 6040,
"errors": []
}Extracts the embedded factur-x.xml attachment directly from any compliant PDF container.
curl -X POST http://localhost:8080/v1/facturx/extract \
-H "Content-Type: application/pdf" \
--data-binary @invoice.pdf \
-o factur-x.xmlRubrol operates as a stateless HTTP sidecar. Any programming language capable of sending HTTP POST requests can render PDFs in
Ready-to-run clients are located in the examples/ directory:
| Language | Client Implementation | Dependencies | Speed |
|---|---|---|---|
| Python | examples/python/generate_invoice.py |
httpx or urllib (Zero-dep) |
~11ms |
| Node.js | examples/nodejs/generate_invoice.js |
Native fetch (Zero-dep, Node 18+) |
~14ms |
| TypeScript | examples/typescript/generate_invoice.ts |
@types/node |
~14ms |
| Go | examples/go/main.go |
Standard library net/http |
~8ms |
| Rust | examples/rust/src/main.rs |
reqwest, tokio |
~7ms |
| cURL / Bash | examples/curl/generate_invoice.sh |
curl |
~9ms |
| PHP | examples/php/generate_invoice.php |
Native curl_* |
~12ms |
| C# / .NET | examples/csharp/Program.cs |
System.Net.Http |
~10ms |
import httpx
payload = {
"template": "b2b_invoice",
"data": {"invoice_number": "INV-2026-001", "total": 1800.00},
"pdf_standard": "a-2b"
}
resp = httpx.post("http://localhost:8080/v1/render", json=payload, timeout=5.0)
with open("invoice.pdf", "wb") as f:
f.write(resp.content)const response = await fetch("http://localhost:8080/v1/render", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
template: "b2b_invoice",
data: { invoice_number: "INV-2026-001", total: 1800.00 },
pdf_standard: "a-2b"
})
});
const buffer = Buffer.from(await response.arrayBuffer());
require("fs").writeFileSync("invoice.pdf", buffer);reqBody, _ := json.Marshal(map[string]any{
"template": "b2b_invoice",
"data": map[string]any{"invoice_number": "INV-2026-001", "total": 1800.00},
})
resp, _ := http.Post("http://localhost:8080/v1/render", "application/json", bytes.NewBuffer(reqBody))
defer resp.Body.Close()
outFile, _ := os.Create("invoice.pdf")
io.Copy(outFile, resp.Body)You can inspect precompiled sample PDFs in examples/output/:
b2b_invoice.pdf- Stripe/Linear-style SaaS billing invoice.saas_receipt.pdf- Clean payment receipt with transaction ID and card brand.facturx_invoice.pdf- EU Factur-X / ZUGFeRD 2.2 hybrid container with embeddedfactur-x.xml.board_financial_report.pdf- Multi-column executive financial briefing.compliance_certificate.pdf- Cryptographically styled SOC 2 / ISO 27001 certificate.
Rubrol uses plain, version-controllable Typst (.typ) files. No HTML hacks, no CSS print media bugs.
In your .typ template, parse the JSON payload injected by Rubrol via sys.inputs:
// Ingest JSON string from Rubrol engine
#let raw_data = sys.inputs.at("data", default: "{}")
#let data = if type(raw_data) == str { json(bytes(raw_data)) } else { raw_data }
// Extract variables with type-safe fallbacks
#let invoice_number = data.at("invoice_number", default: "INV-0001")
#let total = data.at("total", default: 0.0)
#let line_items = data.at("line_items", default: ())Typst supports native scripting constructs:
// Conditional badge
#if data.at("status", default: "PAID") == "PAID" [
#rect(fill: rgb("#ecfdf5"), radius: 4pt, inset: (x: 8pt, y: 4pt))[
#text(fill: rgb("#059669"), weight: "bold", size: 9pt)[PAID]
]
]
// Dynamic table rendering
#table(
columns: (1fr, auto, auto, auto),
align: (left, right, right, right),
table.header([*Description*], [*Qty*], [*Unit Price*], [*Amount*]),
..line_items.map(item => (
item.description,
str(item.qty),
"$" + str(item.unit_price),
"$" + str(item.qty * item.unit_price)
)).flatten()
)Set page rules, headers, and footer page counters:
#set page(
paper: "a4",
margin: (x: 2cm, top: 2.5cm, bottom: 2.5cm),
header: align(right)[
#text(size: 8pt, fill: rgb("#9ca3af"))[Confidential Document]
],
footer: locate(loc => {
let page_number = counter(page).at(loc).first()
let total_pages = counter(page).final(loc).first()
align(center)[
#text(size: 8pt, fill: rgb("#6b7280"))[Page #page_number of #total_pages]
]
})
)Rubrol can bundle system fonts or local font directories:
- Include logos using relative paths:
#image("assets/logo.png", width: 80pt) - Specify custom font families:
#set text(font: "Inter", size: 10pt)
Note
Universal Document Engine with Built-in European Compliance While Rubrol is designed as a universal, high-throughput document compiler for any document (SaaS billing, executive reports, certificates, and receipts worldwide), it includes first-class turnkey compliance for organizations billing European customers under EN 16931 (Factur-X in France, ZUGFeRD in Germany) without requiring third-party JVM tools or complex glue scripts.
Starting in 2026/2027, European B2B transactions legally mandate hybrid electronic invoices compliant with EN 16931.
Rubrol automates this end-to-end:
- Visual Layer: Compiles human-readable PDF/A-3b conforming to ISO 19005-3.
- Data Layer: Validates line-item math and generates schema-valid UN/CEFACT CII XML (
factur-x.xml). - Packaging Layer: Embeds XML into the PDF container with
/AFRelationship /AlternativeXMP metadata.
# 1. Compile Factur-X container (uses default b2b_invoice.typ & facturx_invoice.json)
python rubrol.py facturx --output invoice_facturx.pdf
# Or specify custom template and data payload:
python rubrol.py facturx \
--template rubrol/templates/b2b_invoice.typ \
--data rubrol/data/facturx_invoice.json \
--output invoice_facturx.pdf
# 2. Validate PDF container compliance against EN 16931
python rubrol.py validate-facturx invoice_facturx.pdf
# 3. Extract embedded XML
python rubrol.py extract-facturx invoice_facturx.pdf -o factur-x.xmlRun the official pre-built multi-arch image from GitHub Container Registry:
docker run -d -p 8080:8080 --name rubrol-sidecar ghcr.io/maxcomperatore/rubrol:latestOr build locally from source:
docker build -t rubrol:latest .
docker run -d -p 8080:8080 --name rubrol-sidecar rubrol:latestversion: '3.8'
services:
app:
image: mycompany/api:latest
depends_on:
rubrol:
condition: service_healthy
environment:
RUBROL_URL: http://rubrol:8080
rubrol:
image: rubrol:latest
build:
context: .
dockerfile: rubrol/docker/Dockerfile
ports:
- "8080:8080"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"]
interval: 10s
timeout: 3s
retries: 3
deploy:
resources:
limits:
cpus: '1.0'
memory: 128M
reservations:
cpus: '0.1'
memory: 32MDeploy Rubrol as a co-located sidecar container inside your application Pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: billing-service
spec:
replicas: 3
template:
spec:
containers:
# Your application container
- name: billing-api
image: mycompany/billing-api:v2
env:
- name: RUBROL_ENDPOINT
value: "http://127.0.0.1:8080"
# Rubrol PDF Engine sidecar
- name: rubrol-sidecar
image: rubrol:latest
ports:
- containerPort: 8080
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
cpu: 500m
memory: 128Mi
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 3
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 2
periodSeconds: 5Rubrol operates on the transparent Sidekiq commercial open-core model:
| Tier | Price | Model | Deliverables & Rights |
|---|---|---|---|
| Rubrol Community | $0 / Free Forever | Open Source (GNU LGPLv3) | Local developer CLI, Docker evaluation container, standard B2B SaaS Typst templates, community GitHub support. |
| Rubrol Pro | $1,800 / year | Annual Commercial License | Unlimited local Docker sidecar execution (no doc limits), commercial rights replacing LGPLv3, SaaS billing and receipt templates, standard ISO 19005-2 PDF/A-2b compilation, private GitHub vault access (rubrol-pro-vault), 1-year offline cryptographic license key. |
| Rubrol Enterprise | $4,800 / year | Annual Enterprise Suite | Turnkey EU compliance suite with certified ISO 19005-3 PDF/A-3b + Factur-X / ZUGFeRD 2.2, Schematron semantic validator (EN 16931 & XRechnung 3.0), German DIN 5008 & French Chorus Pro templates, dual vault access (rubrol-pro-vault + rubrol-enterprise-vault), 2025-2028 legal update feed, priority support. |
- Buy Rubrol Pro ($1,800/yr via Stripe Checkout)
- Buy Rubrol Enterprise ($4,800/yr via Stripe Checkout)
Note: Upon purchase, you will receive an immediate signed 1-year offline cryptographic key (RUBROL_LICENSE_KEY=RBL-LIC-...) and automated GitHub collaborator invitations to the private vaults.
Rubrol Pro and Rubrol Enterprise are commercial extensions and licensing agreements for the Rubrol engine. They provide production commercial rights (replacing the GNU LGPLv3), private GitHub template vault access, cryptographic 1-year offline license keys, turnkey EU Factur-X / Schematron compliance suites, and direct developer support.
We do not have pre-sales demos or trial keys. Rubrol Community is 100% free, open-source, and available on GitHub for evaluation and local development under the GNU LGPLv3. If Rubrol meets your performance needs, you can purchase Rubrol Pro or Enterprise. If you are not satisfied with the result, write to support@rubrol.com within 14 days and we will issue a full refund.
For Rubrol Pro ($1,800/yr), pricing is fixed and flat with zero discounts or special deals. For Rubrol Enterprise ($4,800/yr), multi-year commitments or custom cluster volume agreements are available for high-throughput organizations. Contact enterprise@rubrol.com for quotes.
The open-source core is licensed under the GNU Lesser General Public License v3.0 (LGPLv3). Rubrol Pro and Rubrol Enterprise are commercial licenses that replace the LGPLv3 with a traditional proprietary commercial agreement for production SaaS deployments, removing open-source linking obligations.
Every organization running Rubrol in production for commercial SaaS applications must purchase an annual subscription ($1,800/yr). There is no limit to the number of Docker containers, Kubernetes pods, CPU cores, or developer machines used by that organization. Your subscription renews automatically each year.
Every organization deploying Rubrol for European e-invoicing compliance (EN 16931) must purchase a Rubrol Enterprise subscription ($4,800/yr). It includes the complete turnkey compliance suite: certified ISO 19005-3 PDF/A-3b container generation, embedded Factur-X / ZUGFeRD 2.2 XML, built-in Schematron semantic validation (XRechnung 3.0), French Chorus Pro and German DIN 5008 templates, dual vault repository access (rubrol-pro-vault + rubrol-enterprise-vault), guaranteed regulatory update feeds for 2025-2028 EU mandates, and priority Slack/email support.
You can purchase in seconds via Stripe Checkout:
Enter your GitHub Username during checkout. Your account will automatically receive a collaborator invitation granting full access to clone the private repository, and a signed 1-year cryptographic license key (RUBROL_LICENSE_KEY=RBL-LIC-...) will be issued immediately.
Yes. Purchase a Rubrol Enterprise subscription and email support@rubrol.com. We will cancel your existing Pro subscription and prorate the unused balance back to your credit card immediately.
We email you an automated reminder one week before annual subscription renewal. If your card cannot be charged, Stripe will retry 3 times over a 7-day period. If payment continues to fail, your subscription is canceled, private GitHub vault repository access is revoked, and your offline license key will not be renewed upon expiration.
The standard commercial license covers your organization's own SaaS infrastructure and internal servers. If you distribute Rubrol binaries or containers embedded directly inside an on-premise software appliance delivered to external third-party customer hardware, contact enterprise@rubrol.com for an OEM Appliance License.
Licenses are not transferable between different corporate entities. You can transfer a license between employees or GitHub accounts within the same organization by emailing support@rubrol.com with your Stripe customer email.
Your purchase provides private GitHub vault repository access and an offline cryptographic license key. The license agreement requires you to keep these access credentials confidential. Do not commit your license key to public git repositories or public container registries.
Yes. Your developers and CI/CD runners require the RUBROL_LICENSE_KEY environment variable to compile production documents without evaluation limits. Store it securely in your secret manager (e.g. AWS Secrets Manager, GitHub Actions Secrets, HashiCorp Vault, Doppler, or local .env).
Ensure your environment variable RUBROL_LICENSE_KEY starts with RBL-LIC-. Run rubrol license verify from the CLI or inspect container logs on startup. If the key has expired or the signature was modified, the engine will output a clear error message indicating whether the token was malformed or expired.
Yes, up to 14 days after purchase. If Rubrol does not fit your infrastructure or workload, write to support@rubrol.com and we will refund 100% of your payment.
Rubrol Pro is credit card only via Stripe. For Rubrol Enterprise, annual invoicing with payment via ACH, wire transfer, or corporate purchase order is available for qualified corporate accounts. Contact enterprise@rubrol.com to arrange an invoice.
If an unfamiliar charge appears on your card statement, please contact support@rubrol.com before initiating a bank dispute. Disputes result in immediate automated suspension of license keys and vault access. We resolve billing issues and refunds quickly and politely.
Resellers are welcome to purchase Rubrol Pro or Rubrol Enterprise for their clients via Stripe Checkout. Provide the client's distinct technical email address and GitHub username so access is provisioned directly to their engineering team.
Rubrol runs 100% locally within your own Docker containers, Kubernetes pods, or bare-metal servers. Customer documents, invoice data, and PII are processed entirely in memory and never leave your infrastructure. There are zero outbound document telemetry calls, zero third-party analytics scripts, and zero cloud dependencies.
- General Support & Licensing: support@rubrol.com
- Enterprise Sales & Invoicing: enterprise@rubrol.com
- GitHub Repository: https://github.com/maxcomperatore/rubrol
We welcome pull requests for new open-core document templates, client examples, Docker optimizations, and performance improvements.
Please review our Contributing Guide (CONTRIBUTING.md) for:
- Local development setup in under 30 seconds
- Typst template design conventions and dynamic data binding standards
- Conventional commit standards (
feat:,fix:,perf:,template:) - Testing against the local HTTP sidecar
Chromium must initialize an entire browser rendering pipeline: Blink layout engine, V8 JavaScript engine, DOM tree construction, CSS rule calculation, and Skia paint calls. Typst is a purpose-built document layout compiler written in Rust that compiles directly to vector PDF primitives in memory with zero browser overhead.
Typst automatically detects installed system fonts. You can pass --font-path to the CLI or configure custom font directories in your Docker container. All fonts used in PDF/A documents are subset and embedded directly into the output file.
Yes. Pass "format": "svg" or "format": "png" in your POST /v1/render request. This is ideal for generating real-time document preview thumbnails for web apps.
Yes. The Python server uses ThreadedHTTPServer and each Typst compilation worker runs independently in isolated memory spaces without shared mutable state.