Invoices
Render invoice line items and attach structured invoice data.
Render line items and totals as a paged document. If your invoice format requires embedded XML, add it as an attachment with the required PDF/A and XMP settings.
A plain invoice
Line items flow across pages. A footer carries the page counter. measure returns the band's height, so the bottom margin always clears it:
import { } from "@takumi-rs/helpers";
import { , } from "takumi-pdf";
import { , } from "takumi-pdf/primitives";
const = (
< ="flex w-full justify-between px-12 text-[10px] text-[#6b7280]">
<>Invoice {.}</>
< ="flex">
Page < /> of < />
</>
</>
);
const = await (["Inter"]);
const { } = await (, { : "a4", });
const = await (< ={} />, {
: "a4",
: { : 48, : + 32, : 48, : 48 },
,
,
});Use break-inside: avoid to keep a line item together when it fits on a page. In Tailwind, use break-inside-avoid:
import "takumi-pdf";
< ="flex break-inside-avoid gap-3 pt-3 text-xs">
< ="flex-1">{.}</>
< ="w-[100px] text-right">{.}</>
</>;Apply the same style to the totals block.
Electronic invoices
Factur-X and ZUGFeRD combine a readable PDF invoice with structured XML. Configure the container for the profile you are implementing:
| The standard requires | The option |
|---|---|
| A PDF/A-3 container | pdfa: "3b" |
| The XML attached by name | attachments |
An fx: XMP block | metadata.xmp |
| A modification date per file | modificationDate |
| Embedded subset fonts | always on |
Each attachment's modificationDate falls back to metadata.creationDate. Setting the document date once covers both.
import { } from "takumi-pdf";
const = await (, {
: "en",
: "3b",
: "ua1",
: {
: "Invoice INV-2026-0042",
: "2026-08-06",
: [],
},
: [
{
: "factur-x.xml",
: ,
: "text/xml",
: "Factur-X 1.0 MINIMUM invoice data",
: "data",
},
],
});The renderer checks PDF conformance while writing. It does not validate invoice XML, tax rules, or acceptance by a receiving system.
Takumi does not build the invoice XML. Use a library for the profile, or emit the elements the profile lists. The e-invoice example writes a MINIMUM profile by hand.
Validating the result
Two validators cover the two halves. Both need Java.
veraPDF checks the container:
verapdf --flavour 3b --format text invoice.pdf
verapdf --flavour ua1 --format text invoice.pdfMustang checks the Factur-X half, both the XML and the packaging:
java -jar Mustang-CLI.jar --action validate --source invoice.pdfMustang finds the profile through the fx: XMP block. Takumi writes the values and the schema description PDF/A demands, so the two cannot drift. It does not check the values: a wrong profile name surfaces in Mustang, not at render time.
Accessible invoices
For PDF/UA-1 output, set tagged: "ua1" and supply the required metadata. Review the reading order and table semantics as well. See PDF/A and PDF/UA.
Reproducible bytes
Use a fixed metadata.creationDate with the same content, resources, and renderer version when you need reproducible bytes. A new date changes the file even if the invoice looks the same.
Last updated on