Skip to content
Typst-Leitfaden
typstgen
01 / Product
GuideGuide · Typst · Open source

Documents you can
rebuild

02 / Core

From the first letter to the archived e-invoice: how to generate documents from data with Typst, check them, store them and prove later that they are unchanged – with an AI agent, too.

Every command and output on this page is real, run with typstgen 0.4 and Typst 0.15.1 (as of 12 October 2026). Examples and diagrams are in German.

03 / Facts
typstgen 0.4 · Typst 0.15
PDF/A, PDF/UA, ZUGFeRD
MCP for AI agents
01 — Getting started

Why Typst

Typst is a typesetting system: you write text with a little markup into a file, and Typst turns it into a PDF.

Compared with a word processor, everything lives in a readable text file that can be versioned, compared and compiled automatically – the same source gives the same PDF. Compared with LaTeX, the syntax is shorter, errors name file, line and column, and templates are functions in a real programming language.

Headings start with =, bold text sits between asterisks (*bold*), functions start with #: #table(…), #image(…), #bibliography(…). Formulas sit between dollar signs. Data comes into the document with json(…), csv(…) or yaml(…).

This guide uses typstgen: a small tool that compiles .typ files to PDF with an embedded Typst engine – as a command line, a Rust library, WebAssembly and an MCP server for AI agents. No typst installation is needed.

Hands-onFirst document

A letter in twenty lines

GoalWrite a file, compile it and see how typstgen reports an error.

  1. 1

    Source

    Set page format and font, then plain text, a heading and a table.

    #set page(paper: "a4", margin: 2.5cm)
    #set text(lang: "de", font: "Libertinus Serif", size: 11pt)
    
    #align(right)[Musterstadt, #datetime.today().display("[day].[month].[year]")]
    
    = Angebot für die Dokumentenstrecke
    
    Sehr geehrte Frau Beispiel,
    
    vielen Dank für Ihre Anfrage. Wir schlagen vor:
    
    #table(
      columns: (1fr, auto),
      table.header([*Leistung*], [*Preis*]),
      [Vorlagen für Brief und Rechnung], [1.200 €],
      [PDF-Erzeugung in der CI], [600 €],
    )
  2. 2

    Compile

    typstgen writes the PDF next to the source and prints its path.

    $ typstgen compile brief.typ
    brief.pdf
  3. 3

    A typo

    table.header becomes table.heder. typstgen stops, names file, line and column and exits with code 1 – which scripts, CI and AI agents rely on later.

    $ typstgen compile brief-fehler.typ
    error: typst compilation failed:
    brief-fehler.typ:14:9: error: function `table` does not contain field `heder`
Result

A PDF with date, heading and table. The date comes from datetime.today(); the archive chapter shows how to fix it for reproducible files.

First page of the letter: place and date at the top right, a heading, salutation and a table with two services and prices
brief.pdf, compiled with typstgen.
02 — Overview

From data to a verified archive

A document comes from data and a template. What happens next decides whether it can still be trusted in eight years.

check reports errors with file, line and column, preview shows a page as an image, compile writes the PDF – as PDF/A if needed, and for invoices with embedded ZUGFeRD XML.

A manifest records what each PDF was built from. verify rebuilds it later and compares byte for byte. The three checking steps are available to an AI agent over MCP as well.

Fokus
Ablauf mit typstgen
Ablauf mit typstgenDaten und Vorlage ergeben den Quelltext; check und preview zeigen Fehler und Layout, compile erzeugt das PDF/A (bei Rechnungen mit ZUGFeRD-XML) und protokolliert es im Manifest; verify belegt später, dass nichts verändert wurde.ErstellenPrüfenAblegenauch per MCP (KI-Agent)Daten → DokumentDokument → checkcheck → Fehlerfrei?Fehlerfrei? → Dokument: neinFehlerfrei? → preview: japreview → compilecompile → ManifestManifest → verify: später, in CIneinjaspäter, in CIDaten – JSON, BibTeXDatenJSON, BibTeXDokument – .typ + VorlageDokument.typ + Vorlagecheck – Fehler mit ZeilecheckFehler mit ZeileFehlerfrei?Fehlerfrei?preview – Seite als BildpreviewSeite als Bildcompile – PDF/A, ZUGFeRDcompilePDF/A, ZUGFeRDManifest – SHA-256ManifestSHA-256verify – Neubau identischverifyNeubau identisch

Quelle: typstgen 0.4 (Branch-Stand 11.10.2026)

Diagrammdaten anzeigen
Daten zu Ablauf mit typstgen
SchrittArtBahnGruppeFührt zu
DatenStartErstellenDokument
DokumentSchrittErstellencheck
checkSchrittPrüfenauch per MCP (KI-Agent)Fehlerfrei?
Fehlerfrei?EntscheidungPrüfenauch per MCP (KI-Agent)Dokument (nein), preview (ja)
previewSchrittPrüfenauch per MCP (KI-Agent)compile
compileSchrittAblegenManifest
ManifestSchrittAblegenverify (später, in CI)
verifyEndeAblegen

Diagram labels in German.

03 — Create

Tools and templates

For most documents, typstgen and a template are enough. Reports generated from program code call for a library.

typstgen compiles any .typ file. It finds templates through template_paths in typstgen.toml and loads Typst packages such as @preview/… from the same folders as the Typst CLI – or not at all, if configured that way.

business-templates provides 19 business documents as a Typst package: invoice, offer, credit note, reminder, delivery note, order confirmation, letter, credentials, concept, contract, documentation, proposal, minutes, SLA, specification, task list, time sheet and handout. Accounting documents take JSON data, the others named parameters and the text as content. The layout is German (DIN 5008).

RenderReport is a Rust library for data-driven reports built from components (scores, findings, tables, charts), with Typst as the embedded engine; every PDF is PDF/UA-1.

Templates

Three documents from business-templates

Offer – example data "it-consultant".
Offer with letterhead, recipient address, item table and totals

Offer – example data "it-consultant".

Project proposal, title page.
Title page of a project proposal with project details in a framed box and tags at the bottom

Project proposal, title page.

Meeting minutes, title page.
Title page of meeting minutes with date, place, chair, participants and apologies

Meeting minutes, title page.

Generated with typstgen 0.4.1 from the example data in the typst-business-templates repository, 12 October 2026.

04 — Manage

Data, source, PDF – stored apart

The data changes. The template stays. The PDF is just the result.

A folder per document type and year works well, with the document number as file name: invoices/2026/RE-2026-001.json holds the data, RE-2026-001.typ next to it is a thin wrapper that brings template and data together. Master data such as company.json lives once, centrally.

Data, wrapper and manifest are small text files and belong in version control; the history shows who changed what and when. PDFs belong in the archive storage, not in Git – the manifest ties both together.

If you keep a knowledge base for AI systems, store a compact summary of each case there and point to the source with document_id and typst_source. The system reads the entry, the customer gets the PDF; PDFs stay out of the search index.

05 — Academic work

A seminar paper with references

Title page, outlines, formulas, citations and appendix come from a package – the paper itself is just text.

The @local/thesis template lives in typstgen’s examples. It sets title page, abstract, table of contents, lists of figures and tables, roman and arabic page numbers, numbered equations, bibliography, appendix and declaration of authorship – in German or English.

Citations use @key from a BibTeX or Hayagriva file; Typst ships the styles, such as APA, IEEE, Chicago or ISO 690. Figures such as flow diagrams come in as SVG, for example from Chartlet.

Page of a seminar paper with numbered chapters, a formula, APA citations and a table
examples/thesis.pdf, page 4 – PDF/A-2b.
Hands-onScience

Build a paper offline and reproducibly

GoalCompile the seminar paper as PDF/A-2b without fetching anything from the network.

  1. 1

    Configuration

    The template is a package inside the project; downloads and system fonts are off.

    # typstgen.toml
    template_paths = ["templates"]
    package_path = "packages"      # enthält local/thesis/0.1.0
    download_packages = false      # nichts nachladen
    use_system_fonts = false
  2. 2

    Compile

    Fix the standard and the timestamp – two runs give byte-identical files.

    $ typstgen compile thesis.typ --config typstgen.toml \
        --pdf-standard a-2b --creation-timestamp 1759276800
    thesis.pdf
  3. 3

    When a package is missing

    With download_packages = false the build stops instead of fetching:

    Output
    error: typst compilation failed:
    paper.typ:1:9: error: package not found (searched for @preview/oxifmt:0.2.1)
Result

Seven pages with outlines, a Chartlet figure, a formula, a table and five real sources in APA style; veraPDF reports PDF/A-2b compliant.

Page of the seminar paper with a flow diagram in three columns, a table and a code block below
Figure 1, made with Chartlet, page 5.
06 — Business

Invoices with ZUGFeRD

Since 2025, businesses in Germany must be able to receive e-invoices; they must issue them from 2028 at the latest.

A ZUGFeRD invoice is a PDF/A-3 that carries the same data a second time as XML (UN/CEFACT CII, profile EN 16931). For VAT, the XML is the leading part.

typstgen builds the XML from the same JSON data the invoice template renders. It recomputes lines, VAT per category and totals first; if the JSON states different numbers, the build fails – otherwise the PDF would show something else than the XML. Covered: standard and reduced rate, 0 %, exempt with a reason, and reverse charge.

E-Rechnungspflicht im inländischen B2B-Verkehr
E-Rechnungspflicht im inländischen B2B-VerkehrSeit 2025 müssen Unternehmen E-Rechnungen empfangen können. Papier- und andere Rechnungen sind beim Ausstellen bis Ende 2026 erlaubt, 2027 nur noch bei höchstens 800.000 Euro Vorjahresumsatz; ab 2028 ist die E-Rechnung allgemein Pflicht.01.202507.202501.202607.202601.202707.202701.2028Empfang Pflicht: 01.01.202501.01.2025Empfang PflichtPapier und andere Formate erlaubt: 01.01.2025 – 31.12.202601.01.2025 – 31.12.2026Papier und andere Formate erlaubtnur bis 800.000 € Vorjahresumsatz: 01.01.2027 – 31.12.202701.01.2027 – 31.12.2027nur bis 800.000 € VorjahresumsatzEDI-Verfahren zulässig: 01.01.2025 – 31.12.202701.01.2025 – 31.12.2027EDI-Verfahren zulässigE-Rechnung allgemein Pflicht: 01.01.202801.01.2028E-Rechnung allgemein Pflicht

Quelle: § 27 Abs. 38 UStG; BMF-Schreiben vom 15.10.2024 und 15.10.2025 (Stand 11.10.2026)

Diagrammdaten anzeigen
Daten zu E-Rechnungspflicht im inländischen B2B-Verkehr
EintragArtBeginnEndeNach
Empfang PflichtMeilenstein01.01.2025
Papier und andere Formate erlaubtPhase01.01.202531.12.2026
nur bis 800.000 € VorjahresumsatzPhase01.01.202731.12.2027Papier und andere Formate erlaubt
EDI-Verfahren zulässigPhase01.01.202531.12.2027
E-Rechnung allgemein PflichtMeilenstein01.01.2028nur bis 800.000 € Vorjahresumsatz, EDI-Verfahren zulässig

Diagram labels in German.

Hands-onE-invoice

Create and check a ZUGFeRD invoice

GoalTurn rechnung.json and company.json into a PDF/A-3 with embedded XML and check it with the Mustang validator.

  1. 1

    Document

    Two lines: load the template, pass the data. The package lives in the typst-business-templates repository under packages/local/business-templates/0.1.0; package_path in typstgen.toml points to it.

    #import "@local/business-templates:0.1.0": invoice
    #invoice(data: json("/rechnung.json"), company: json("/company.json"))
  2. 2

    Compile

    --zugferd and --company build the XML from the same data and embed it as factur-x.xml.

    $ typstgen compile rechnung.typ --pdf-standard a-3b \
        --creation-timestamp 1737500000 \
        --zugferd rechnung.json --company company.json
    rechnung.pdf
  3. 3

    Check

    Mustang checks the PDF/A-3 and the XML against EN 16931.

    $ java -jar Mustang-CLI-2.26.0.jar --action validate --source rechnung.pdf
    … Parsed PDF:valid XML:valid … Profile:urn:cen.eu:en16931:2017 Version:2 … Errors:[]
  4. 4

    When the data is wrong

    Every problem at once, each with the field that fixes it:

    Output
    error: ZUGFeRD invoice:
    recipient.address.country: unknown country, set recipient.address.country_code (ISO 3166-1, e.g. "DE")
    items[0]: unit "Kisten" has no UN/ECE code, set items[0].unit_code (e.g. "C62")
    items[1]: total 1.00 does not match quantity × unit price = 11200.00
Result

A valid ZUGFeRD PDF in the EN 16931 profile; veraPDF reports PDF/A-3b compliant. Mixed VAT rates, reverse charge and an exempt invoice were checked as well.

First page of an invoice with sender, recipient, item table and totals; a logo placeholder at the top right
Invoice from the "it-consultant" example; the example company has no logo.
07 — Archive

Keep and prove

PDF/A keeps a file readable. That it is unchanged has to be shown separately.

typstgen compile --manifest archive.json records for each PDF which source, which options and which files it was built from – with SHA-256 of the PDF, templates, data, images, package files and fonts.

typstgen verify later checks three things: the stored PDF is unchanged, a rebuild reads the same files, and it produces the same bytes. That needs a fixed timestamp and pinned fonts and packages for every document.

Aufbewahrungsfristen seit 1. Januar 2025
Aufbewahrungsfristen seit 1. Januar 2025Bücher und Jahresabschlüsse zehn Jahre, Rechnungen und andere Buchungsbelege acht Jahre, Handels- und Geschäftsbriefe sechs Jahre.0246810JahreBücher, Jahresabschlüsse: 1010Bücher, JahresabschlüsseRechnungen, Buchungsbelege: 88Rechnungen, BuchungsbelegeHandels- und Geschäftsbriefe: 66Handels- und Geschäftsbriefe

Quelle: § 147 Abs. 3 AO, § 257 Abs. 4 HGB, § 14b UStG (Stand 11.10.2026)

Diagrammdaten anzeigen
Daten zu Aufbewahrungsfristen seit 1. Januar 2025
KategorieWert
Bücher, Jahresabschlüsse10
Rechnungen, Buchungsbelege8
Handels- und Geschäftsbriefe6

Diagram labels in German: books and annual accounts 10, invoices and vouchers 8, business letters 6 years.

Hands-onArchive

Record a build and verify it

GoalCreate a PDF with a manifest, verify it, change the source and see what verify reports.

  1. 1

    Record and verify

    $ typstgen compile brief.typ --pdf-standard a-2b \
        --creation-timestamp 1790000000 --manifest archive.json
    brief.pdf
    $ typstgen verify
    ok      brief.pdf
    1 of 1 documents verified
  2. 2

    The source changes

    A price in brief.typ changes without recording again. verify names the file and exits with code 1.

    $ typstgen verify
    FAILED  brief.pdf
            changed: brief.typ
            the rebuild differs from the recorded PDF
    0 of 1 documents verified
Result

Any change to source, data, template, package or font shows up – and so does a changed PDF. Once the change is undone, verify reports "1 of 1 documents verified" again.

08 — Automate

Check before every push

Locally the check is binding; in CI it is the proof at release time.

typstgen verify runs before every push – as a script or a pre-push hook. CI has no PDFs, since they live in the archive; there, verify --rebuild-only checks only that every source yields the recorded bytes.

For a rebuild on another machine to match, fonts and packages belong in the repository: use_system_fonts = false, font_paths = ["fonts"], package_path with download_packages = false. A template that asks for a system font such as Helvetica looks different on Linux otherwise.

GitHub Actions

verify as a release check

.github/workflows/verify.ymlYAML
on:
  push:
    tags: ["v*"]
  workflow_dispatch:

jobs:
  verify:
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v4
      - run: cargo install typstgen --version 0.4.1 --locked
      - run: typstgen verify archive.json --rebuild-only
09 — Bring in AI

An agent that finds its own mistakes

An AI agent writes Typst quickly – and makes mistakes. Over MCP it can find and fix them itself.

typstgen mcp is a Model Context Protocol server on stdin/stdout with four tools: check (errors with line and column, writes nothing), preview (a page as an image), compile (PDF, optionally PDF/A or ZUGFeRD) and list_templates. All paths are confined to the workspace.

A division of labour works well: the agent writes data (JSON) and text, the template takes care of the layout, and a person reviews the result before it goes out. For e-invoices the data comes from bookkeeping, not from the language model.

Hands-onAI & MCP

An MCP session: check, fix, compile

GoalConnect typstgen to Claude Code and follow an agent repairing a broken offer.

  1. 1

    Set up

    For the current project; other MCP clients start the same command.

    $ claude mcp add typstgen -- typstgen mcp --root .
  2. 2

    Find the error

    The agent calls check and gets the error as the tool result.

    Output
    check  angebot.typ
    → typst compilation failed:
      angebot.typ:14:9: error: function `table` does not contain field `heder`
  3. 3

    Fix and compile

    After fixing line 14: check again, look at page 1, compile as PDF/A-2b.

    Output
    check    angebot.typ   → ok, 1 page
    preview  angebot.typ   → image/png (Seite 1)
    compile  angebot.typ, pdf_standards ["a-2b"]
             → wrote angebot.pdf (21090 bytes), 1 page
Result

The session ran over the real protocol (JSON-RPC over stdio); the output above is the tool results, trimmed to the essentials.

Reference

Frequent questions

Does Typst have to be installed?

No. typstgen includes Typst as a library. For your own experiments, the editor on typst.app is still worth it.

Is PDF/A required?

Not by German law (as of 11 October 2026). PDF/A is the container of ZUGFeRD and common for long-term archiving.

Can I move my LaTeX paper over?

BibTeX files carry over directly. The text is moved by hand or with converters; formulas are shorter in Typst but written differently.

Why do PDFs not belong in Git?

They are results. Data, sources and the manifest belong in Git; the PDF can be rebuilt from them at any time, and verify shows it is the same.

What happens with a Typst update?

A new Typst version may typeset differently. verify then names both versions; archived PDFs stay valid, and a rebuild should use the recorded version.