Skip to content

Generate PDF invoices in PHP without a headless browser

A native extension compiles Typst templates to print-ready PDFs inside your PHP application. No shelling out to binaries, no browser process, no per-document fees.

PHP teams generating PDFs usually pick between HTML-to-PDF libraries that struggle with page breaks and fonts, the abandoned wkhtmltopdf, or running a headless browser next to the application.

Oicana compiles PDFs in process through a native PHP extension instead. Install the oicana/oicana Composer package, load a packed template once, and compile documents from JSON:

use Oicana\Template;
$template = new Template(file_get_contents('invoice-0.1.0.zip'));
try {
$pdf = $template->export(
jsonInputs: ['invoice' => [
'number' => '2026-001',
'customer' => 'Acme GmbH',
'total' => '€1,190.00',
]],
);
} finally {
$template->cleanup();
}

A warmed up template produces a print-ready PDF in single digit milliseconds, directly in your application.

The snippet loads invoice-0.1.0.zip, a packed Oicana template. Templates are plain Typst projects: a typst.toml manifest declares a JSON input named invoice, and main.typ uses it:

main.typ
#import "@preview/oicana:0.2.0": setup
#let read-project-file(path) = read(path, encoding: none)
#let (input, oicana-image, oicana-config) = setup(read-project-file)
#set document(date: datetime.today())
= Invoice #input.invoice.number
Billed to: #input.invoice.customer
*Total: #input.invoice.total*

Running oicana pack in the template directory produces the zip. Create a Template walks through the manifest and input definitions, and the open source example templates include a complete invoice.

The Composer package installs a native extension through an installer plugin: register the composer.oicana.com repository, allow the plugin, and require oicana/oicana. The installer prints the exact command to activate the extension, and vendor/bin/oicana-env reprints it anytime.

For production, use a long-running application server like RoadRunner. It keeps your PHP worker alive, so templates are loaded once and stay in memory across requests. The Slim example project includes a RoadRunner setup, blob inputs, error handling, and request validation.

No headless browser

A native extension compiles PDFs inside PHP. No shelling out to wkhtmltopdf, no browser process to deploy.

Your data stays with you

Documents are generated inside your own application. No customer data is sent to a third party, which keeps GDPR and HIPAA compliance in your hands.

Flat price, unlimited documents

One flat license per application, no metering. A hundred invoices a month cost the same as a hundred thousand. Non-commercial use is free.