An invoice can have two readers. A person opens the PDF, checks the amount, and pays it. Or software extracts its data, so it can handle the invoice automatically. A regular PDF mostly serves the first reader and can make it difficult to trust automatic handling of invoices.
ZUGFeRD and Factur-X are standards used in Germany and France that solve this by putting both readers in one file: a normal PDF users can look at, with the structured invoice data embedded as XML for automation. This post explains why you would want or need that and how Oicana produces such a file from a Typst template.
More and more countries require invoices to carry machine-readable data, not just a printed layout. The relevant ones for the standards we are looking at here are:
Germany mandates that businesses can receive structured e-invoices for domestic B2B since 2025, with required sending of e-invoices following in phases over the next years.
France is rolling out a Factur-X based mandate on a similar timeline.
Even where it is not yet required, structured invoices save work. The recipient’s system reads the totals, tax rates, and line items straight from the file. No manual entry, no OCR guesswork, fewer mistakes.
Oicana compiles a Typst template to PDF, and its PDF export can embed files and write custom XMP metadata. That is exactly what the three points above need.
1. Export to PDF/A-3 in the manifest. You declare the standards once, next to the template:
typst.toml
[tool.oicana.export.pdf]
standards = ["ua-1", "a-3b"]
[[tool.oicana.inputs]]
type = "blob"
key = "zugferd"
default = { file = "factur-x.xml" }
Here the invoice XML comes in as a blob input, so you can pass a different one per invoice. The a-3b standard allows embedding files to be a valid e-invoice. Adding ua-1 makes the same document more accessible through PDF/UA-1.
2. Embed the XML in the template. A single line takes the XML bytes, embeds them, and writes the matching XMP metadata:
Accessibility reaches a lot further than websites. It includes the PDFs you generate for your customers. Invoices, statements, contracts, tickets, and reports are part of the service you offer, and services have to be accessible.
This post looks at what the European Accessibility Act and the US accessibility framework (ADA and Section 508) mean for businesses that produce PDFs, whether PDF/UA is actually required, and how Oicana exports PDF/UA-1 documents from Typst templates.
The European Accessibility Act (Directive (EU) 2019/882) became enforceable on 28 June 2025. It requires a broad set of products and services sold in the EU to be accessible to people with disabilities. It includes services like e-commerce, consumer banking, e-books, transport, or telecoms and applies regardless of where your company is based. If you sell into the EU market, you are in scope. Any customer facing PDFs that you generate are part of your service and need to be accessible.
Two important nuances:
Microenterprise exemption (services): organizations with fewer than 10 employees and annual turnover below €2 million are generally exempt for the services parts of the EAA.
A transition window: new products and services have to comply from 28 June 2025. Many existing ones have until 28 June 2030.
Penalties are set by each member state and can be severe. There can be fines, and in some jurisdictions removal of a product or service from the market.
The EAA itself contains no checklist. It points at the harmonized European standard EN 301 549, which in turn incorporates the Web Content Accessibility Guidelines (WCAG) 2.1 Level AA as the technical benchmark for digital content. So in practice, “accessible” means “meets WCAG 2.1 AA”. That applies to document content and to web pages.
Section 508 of the Rehabilitation Act applies to US federal agencies and the vendors that sell to them. Its refresh adopted WCAG 2.0 Level AA as the technical baseline for electronic content, including PDF documents, and the standard is widely paired with PDF/UA to make PDFs conform.
Short answer: not literally, but it is the recognized way to get there for PDFs.
PDF/UA (“Universal Accessibility”, ISO 14289) is the technical standard that defines how an accessible PDF must be built: a complete tag tree, a logical reading order, alternative text for images and formulas, a declared document language and title, and so on. The law mandates the outcome (WCAG conformance), and PDF/UA is the established, testable specification for achieving that outcome in the PDF format.
In other words:
The EAA / EN 301 549 do not name PDF/UA as mandatory. They require WCAG 2.1 AA. PDF/UA is how the PDF industry implements those requirements. A PDF/UA-conformant file carries exactly the tagging, metadata, and structure that WCAG asks for. Pairing PDF/UA conformance with WCAG is widely seen as the safest, most future-proof approach for any organization producing PDFs at scale.
So if you generate PDFs and want a clear, verifiable target, “produce PDF/UA” is the practical goal.
A handful of brochures can be remediated by hand in Acrobat. But the documents that put a business in scope are usually the generated ones: thousands of invoices a day, per-customer statements, contracts assembled from data. You cannot manually tag those after the fact. Accessibility has to be produced at generation time, by the template and the engine, consistently, on every document.
This is where a lot of PDF tooling struggles. Headless-browser HTML-to-PDF pipelines produce weak or no tag trees; many imperative PDF libraries leave tagging entirely to you. Getting reliable, valid tags out of them is a project in itself.
Oicana compiles Typst templates to PDF, and Typst’s PDF export was built with accessibility in mind. Two things matter here:
1. Tagged PDFs by default. Oicana produces tagged (accessible) PDFs out of the box. The tag tree is the foundation everything else builds on. The semantic markup you already write in Typst (= Heading, lists, figure, tables) maps to the corresponding PDF structure elements automatically, so a well-structured template yields a well-structured document.
2. One-line PDF/UA-1 export. You opt into PDF/UA-1 directly in the template manifest:
typst.toml
[tool.oicana.export.pdf]
standards = ["ua-1"]
That is all the integration code needs to know. The same Typst template exports a PDF/UA-1 file whether you compile it from Node.js, Python, Java, Rust, C#, PHP, or the browser. (Oicana’s default standard is PDF/A-3b; PDF/A profiles such as a-2a/a-3a are also tagged and accessibility-oriented if you need PDF/A instead.)
PDF/UA is a contract, and Typst holds you to it. Producing a valid PDF/UA-1 file requires real accessibility metadata in the template, and if something is missing, the compile fails with a clear error rather than silently shipping a broken file. At minimum you need:
a document title and a document language,
alternative text on every image and formula,
genuine semantic structure (headings, lists, tables) instead of visual fakes,
decorative elements marked as artifacts so screen readers skip them.
Accessibility lives in the template, not scattered across application code. Flip one manifest setting and every document your service emits is PDF/UA-1, across all integrations and tech stacks.
Templates are plain text in version control. Accessibility requirements, alt-text conventions, and the standard you target are reviewable and diffable like any other code.
Failures are loud. A missing title or alt text breaks the build, so a regression cannot quietly ship a non-conformant invoice to a customer.
Built on open source. Typst’s compiler and its PDF export are open source, so your accessible-document pipeline isn’t locked to a single vendor.
If accessibility is on your roadmap, generating PDF/UA documents from data is one of the trickier pieces to get right. Oicana makes it a manifest setting on top of a templating system you can read, review, version, and use from many different tech stacks.
Generating PDFs from application code is usually a pick-your-poison choice. HTML-to-PDF tools have fragile pagination and weak typography, PDF libraries put verbose layout code into your application, and SaaS PDF builders often come with proprietary template formats and vendor lock-in.
Oicana takes a different route. Templates are plain Typst projects. Your application passes typed inputs (JSON, images), and Oicana compiles a PDF.
Multi-platform: the same template works across all integrations: browser, Node.js, C#, Java, Rust, Python, and PHP.
Powerful layouting: templates use the full power of Typst, including its package ecosystem.
Performant: PDFs can generate in single digit milliseconds with warmed-up templates in native integrations.
AI and version control ready: templates are text files. They live next to your code, and AI can help write them.
Minimal vendor lock-in: templates are plain Typst projects. The Typst compiler is open source.
Typst is a modern markup-based typesetting system. In main.typ, the = marks a heading and # switches to code mode. The first line imports the Typst Oicana package and the next two lines set it up. In the last line is the actual visual content of our document. #input.info.name interpolates the name field of the info input into the document.
In typst.toml, we define metadata for the template like a name, entrypoint, and inputs. The example defines a single input of type json (see the Oicana documentation on inputs). If the input value is { "name": "Alice" }, the content of our document will be a header reading “Hello from Oicana, Alice”.
There are good options for working on Typst documents like the official webapp and several IDE plugins. this is what it can look like to work on an Oicana template in VS Code using the Tinymist Typst extension with syntax highlighting and live preview:
If you install the Oicana CLI and run oicana pack in the template directory, it produces the file example-0.1.0.zip that any Oicana integration can compile. Passing { "name": "Alice" } for the info input from your application looks like this in the different integrations (omitting some general boilerplate):
Non-commercial use is free: Personal projects, hobby use, research, education, and use by charitable organizations, educational institutions, public research organizations, and government institutions are covered by the PolyForm Noncommercial License.
Commercial licenses are available on the homepage. Licenses are per application, priced by company size, and every subscription includes the CLI and all integrations. All prices include VAT.
Startup: €19/month, for companies up to €2M yearly revenue
Scaleup: €49/month, for companies up to €25M yearly revenue
Enterprise: €99/month, for companies above €25M yearly revenue
Annual billing saves 15%. Every subscription comes with a 30-day money-back guarantee. If Oicana doesn’t fit, email support@oicana.com for a refund.
Oicana was already used in production during the alpha and improved based on the learnings. The same idea goes for the beta. If something feels off, please let us know. That’s the feedback that shapes the road from beta to 1.0.
Give Oicana a try and get started with the setup guide.
We’ve added two new integrations to the lineup: Java and PHP. Together with the existing browser, C#, Node.js, Rust, and Python integrations, Oicana now covers most of the major server-side ecosystems. Check out the getting started documentation to try it out.
Just like the other integrations, the two new ones come with open source example applications. A small Spring Boot Java application and a php service using Slim demonstrate backend services that can generate PDFs from templates and data with Oicana.
The docs have been migrated from Typst to MDX and included in this website. While we love Typst and still plan to eventually use it for the website and the online documentation, there were too many small issues in making the documentation look good in a responsive website.
The Typst version of the documentation will at some point power the online documentation again.
Oicana is approaching beta. For the moment, no new integrations are planned, to focus on improving what we already have. The non-commercial license will stay and pricing for commercial licenses is work in progress. More details on that soon — stay tuned.