Typst Goes First-Class: Document Rendering as a Suite Service
Universities run on documents: theses, exam papers, lecture notes, certificates, and administrative letters. Most of these are still produced by hand or by fragile local tooling. With the latest integration sprint, Typst β a markup-based typesetting system and modern alternative to LaTeX β is now a first-class openEduSuite service, ready to drive deterministic, template-based document production.
Why Typesetting Belongs in the Suite
The suite already covers collaborative editing with its office and editor services. What it lacked was production typesetting: the ability to compile a document from a template and data, reproducibly, on the server. That is a different job β exam papers generated from a registry, certificates produced in batch, letters rendered from structured data β and it calls for a typesetting engine rather than an interactive editor.
An Upstream-Tracked Fork, Not a Split
The suite uses tobias-weiss-ai-xr/typst, a fork of upstream typst/typst with a strict separation policy:
- Weekly upstream sync β a scheduled workflow merges upstream
maininto the fork. Merge conflicts fail the workflow loudly so they get resolved by a human, not silently buried. - Fork-specific code stays in its lane β everything we add lives under
render-service/and.github/workflows/, keeping future upstream merges conflict-free. - Releases follow upstream β the current release,
v0.15.1, carries the upstream version number and is reset on each sync.
The goal is to remain a thin, well-behaved fork: we add deployment value, not engine divergence.
A Render Service with Hard Edges
The new render service is a deliberately small HTTP wrapper around the typst CLI, written with the Python standard library only β no framework, no dependencies to audit:
POST /render {"source": "= Hello", "format": "pdf|png|svg",
"assets": {"data.csv": "..."}} -> document bytes
GET /healthz -> {"status": "ok", "typst": "typst 0.15.1 ..."}
The trust boundary is enforced in-process:
- Request caps (5 MB body, 2 MB source) and a 60-second compile timeout.
- Asset names are restricted to flat identifiers β no path traversal.
- Compilation runs in an isolated temporary directory with root confinement; the compiler performs no network access.
- Compile concurrency is bounded to protect cluster nodes from CPU saturation.
- The container runs the service as an unprivileged user.
- Liberation fonts are baked into the image, covering the metric-compatible Arial/Times/Courier families that most institutional templates assume.
One small lesson from the sprint: even a dependency-free wrapper needs real API tests. A keyword-argument mismatch in the compile path was caught and fixed, and an HTTP end-to-end regression test now guards it.
Images That Ship Themselves
Every release publishes two multi-arch images (linux/amd64 and linux/arm64) to the GitHub Container Registry:
ghcr.io/tobias-weiss-ai-xr/typstβ the pristine typst CLIghcr.io/tobias-weiss-ai-xr/typst-renderβ the render service
The release workflow builds, smoke-tests, and publishes both images automatically, with the smoke-test result keyed to the image digest β so what was tested is provably what was shipped.
Deployment in Both Stacks
| Stack | Wiring |
|---|---|
| Kubernetes (higher education) | Helmfile chart pinned to a release tag |
| Docker Compose (SME) | Dedicated service profile in the compose stack |
Both deployments follow the same discipline as every other suite service: an internal network path only, a /healthz-based liveness probe, and images pinned by release tag. The service is machine-facing by design β template pipelines, admin tooling, and portal backends call the API; it is not exposed directly to browsers. The portal entry for interactive authoring points to the hosted Typst editor instead.
What's Next
- A template repository for institutional documents β exam papers, certificates, letters β consumed by the render API.
- Pipeline integrations, for example generating certificates from registry data on schedule.
- Continued upstream tracking β the weekly sync keeps the fork current with the fast-moving Typst ecosystem.
Call to Action
- Read more: the technical details are documented in the companion article Typst Document Rendering Architecture.
- Try it: point a template pipeline at the render API β a
POST /rendercall with source and assets is all it takes. - Get involved: join the openEduSuite community and help build the template repository.
Deterministic typesetting, deployed like any other service β documents are infrastructure too.
Trademark notice: Typst is a product of typst (typst.app). This article is independent and is not affiliated with, endorsed by, or sponsored by typst. All other product names are trademarks of their respective owners.