Typst vs LaTeX for Math Rendering: A Python Developer's Perspective
When I needed to render mathematical formulas in PDFs from Python, I assumed LaTeX was the only professional option. After spending hours debugging cryptic LaTeX errors and struggling with verbose syntax, I discovered Typst - a modern alternative that produces the same quality output with much cleaner syntax.
The Problem
I was building a scientific report generator for a research team. The reports needed complex mathematical expressions - partial derivatives, integrals, matrices, and equations with various formatting requirements.
I started with LaTeX, the standard for mathematical typesetting. Here’s what a partial derivative looked like:
\frac{\partial f}{\partial x} = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}To render this from Python, I needed a full LaTeX installation plus a Python wrapper:
import subprocessimport tempfileimport os
def render_latex_equation(latex_code, output_path): """Render LaTeX equation to PDF using pdflatex.""" doc = f""" \\documentclass{{article}} \\usepackage{{amsmath}} \\begin{{document}} \\[ {latex_code} \\] \\end{{document}} """
with tempfile.TemporaryDirectory() as tmpdir: tex_file = os.path.join(tmpdir, 'equation.tex') with open(tex_file, 'w') as f: f.write(doc)
# Run pdflatex result = subprocess.run( ['pdflatex', '-interaction=nonstopmode', tex_file], cwd=tmpdir, capture_output=True, text=True )
if result.returncode != 0: # Parse cryptic LaTeX error print("LaTeX Error:") print(result.stderr[-500:]) # Last 500 chars of error return False
# Copy PDF to output pdf_file = os.path.join(tmpdir, 'equation.pdf') os.rename(pdf_file, output_path) return TrueI ran this and got:
$ python latex_renderer.pyLaTeX Error:! Undefined control sequence.l.5 \parital {f}{x}?A typo in my macro name caused an error. The error message was cryptic - it pointed to \parital but didn’t explain the issue clearly. I spent 20 minutes debugging before realizing I had misspelled \partial.
The Core Pain Points
After a week of working with LaTeX, I identified these issues:
1. Verbose Syntax
Even simple fractions require backslashes and braces:
% A simple fraction in LaTeX$\frac{a + b}{c + d}$
% Nested fractions get messy$\frac{\frac{1}{x}}{\frac{y}{z}}$2. Cryptic Error Messages
When I forgot a brace:
! Missing } inserted.<inserted text> }l.15 \frac{a + b}{c + d $?The error pointed to line 15, but the actual missing brace was somewhere else entirely.
3. Slow Compilation
Generating a PDF with 50 equations took 3-5 seconds. For a web service generating thousands of reports, this was too slow.
4. Heavy Dependencies
A full LaTeX installation is 3-5 GB. My Docker images ballooned in size.
Discovering Typst
I found Typst while searching for LaTeX alternatives. Typst is a modern typesetting system designed to be:
- Faster: Compiles documents in milliseconds
- Simpler: Cleaner syntax without sacrificing power
- Integrated: Works as a library, not just a standalone program
Here’s the same partial derivative in Typst:
(partial f) / (partial x) = lim_(h -> 0) (f(x+h) - f(x)) / hNotice the differences:
- No backslashes for common operations
- Parentheses instead of braces (more readable)
- Underscore for subscripts (intuitive)
- Fractions use
/operator
Side-by-Side Comparison
Let me show common mathematical expressions in both syntaxes:
Fractions
% LaTeX$\frac{1}{x + 1}$// Typst$ 1 / (x + 1) $Matrices
% LaTeX$\begin{pmatrix} 1 & 2 \\ 3 & 4\end{pmatrix}$// Typst$ mat( 1, 2; 3, 4) $The Typst version uses semicolons for row separation - much clearer than \\.
Piecewise Functions
% LaTeX$f(x) = \begin{cases} 1 & \text{if } x \geq 0 \\ -1 & \text{if } x < 0\end{cases}$// Typst$ f(x) = cases( 1 "if" x >= 0, -1 "if" x < 0) $Typst uses cases() function with comma separation - easier to read and write.
Integrals
% LaTeX$\int_0^\infty e^{-x^2} \, dx = \frac{\sqrt{\pi}}{2}$// Typst$ integral_0^infinity e^(-x^2) dif x = sqrt(pi) / 2 $Typst uses named functions (integral, infinity) instead of symbols (\int, \infty). More typing, but more readable.
Greek Letters
% LaTeX$\alpha, \beta, \gamma, \delta, \epsilon, \theta, \lambda, \mu, \pi, \sigma, \omega$// Typst$ alpha, beta, gamma, delta, epsilon, theta, lambda, mu, pi, sigma, omega $Same letters, but no backslashes. Typst recognizes Greek letter names directly in math mode.
Chemistry
% LaTeX$\text{H}_2\text{O}$ and $\text{NaCl}$// Typst$ "H"_2"O" "and" "NaCl" $Typst uses quotes for text within math mode.
Using Typst from Python
The real win comes when integrating with Python. GoPdfSuit provides native Typst support:
from pypdfsuit import PdfGenerator
template = { "elements": [ { "type": "math", "content": "integral_0^infinity e^(-x^2) dif x = sqrt(pi) / 2", "syntax": "typst" }, { "type": "text", "content": "The Gaussian integral is a fundamental result in calculus.", "style": {"font": "Helvetica", "size": 12} }, { "type": "math", "content": """ f(x) = cases( 1 "if" x >= 0, -1 "if" x < 0 ) """, "syntax": "typst" } ]}
generator = PdfGenerator(template=template)generator.render({}, "math_document.pdf")I ran a comparison benchmark:
import timefrom pypdfsuit import PdfGenerator
# Generate 100 PDFs with 10 equations eachdef benchmark_typst(): equations = [ "integral_a^b f(x) dif x", "sum_(i=1)^n i^2 = n(n+1)(2n+1)/6", "lim_(x -> 0) sin(x)/x = 1", # ... more equations ]
template = { "elements": [ {"type": "math", "content": eq, "syntax": "typst"} for eq in equations ] }
start = time.time() for i in range(100): generator = PdfGenerator(template=template) generator.render({}, f"output_{i}.pdf") end = time.time()
return end - start
print(f"Typst: {benchmark_typst():.2f}s for 100 PDFs")# Output: Typst: 2.34s for 100 PDFsThe same benchmark with LaTeX via subprocess:
$ python latex_benchmark.pyLaTeX: 15.67s for 100 PDFsTypst was 6-7x faster.
Why This Matters
The cleaner syntax and faster compilation changed my workflow:
Before (LaTeX):
- Write equation with verbose syntax
- Run compiler
- Parse cryptic error message
- Fix typo or missing brace
- Repeat 2-4 until working
- Wait for slow compilation
After (Typst):
- Write equation with intuitive syntax
- Get immediate output (or clear error)
- Done
The readability also improved code reviews. Team members could quickly scan equations and understand what they represent without mentally parsing backslashes and braces.
When LaTeX Still Wins
Typst is not a complete replacement. LaTeX still excels for:
1. Established Document Classes
If you need IEEE, ACM, or specific journal templates, LaTeX has decades of established classes. Typst’s ecosystem is newer.
2. Complex Bibliographies
BibTeX and its variants are deeply integrated into academic workflows. Typst has bibliography support, but it’s less mature.
3. Institutional Requirements
Some universities and journals require LaTeX source files. You can’t submit Typst.
4. Community Packages
LaTeX has thousands of packages for specialized needs. Want to typeset music scores? There’s musixtex. Chess diagrams? skak. Typst’s package ecosystem is growing but smaller.
Migration Tips
If you’re moving from LaTeX to Typst, here’s what I learned:
Start with new documents
Don’t try to convert existing LaTeX files. The syntax is different enough that manual rewriting is faster than conversion tools.
Learn the function names
Typst uses named functions for symbols:
| LaTeX | Typst |
|---|---|
\int | integral |
\infty | infinity |
\sum | sum |
\prod | product |
\sqrt | sqrt |
\partial | partial |
Use the web app for learning
The Typst web app (typst.app) provides real-time preview. I wrote equations there first, then copied them to Python code.
Embrace the whitespace
Typst ignores whitespace in math mode (mostly), so you can format for readability:
// All equivalent$ a+b $$ a + b $$ a + b $Common Mistakes
1. Forgetting math mode delimiters
// WRONG - plain textpartial f / partial x
// CORRECT - math mode$ partial f / partial x $2. Missing parentheses in fractions
// WRONG - ambiguous$ a / b + c $ // Means: (a/b) + c
// CORRECT - explicit$ (a) / (b + c) $ // Means: a / (b + c)3. Using LaTeX syntax
// WRONG - LaTeX syntax doesn't work$ \frac{a}{b} $
// CORRECT - Typst syntax$ a / b $4. Not quoting text in equations
// WRONG - "if" is interpreted as variables i*f$ f(x) = 1 if x >= 0 $
// CORRECT - quoted text$ f(x) = 1 "if" x >= 0 $Performance in Production
For the scientific report generator I mentioned earlier, switching from LaTeX to Typst:
| Metric | LaTeX | Typst |
|---|---|---|
| Docker image size | 3.2 GB | 450 MB |
| PDF generation time (per doc) | 2.3s | 0.38s |
| Memory usage (peak) | 280 MB | 45 MB |
| Error rate | 4.2% | 0.3% |
The error rate dropped dramatically because Typst’s error messages are actionable. When something goes wrong, I can actually fix it without trial and error.
Getting Started
To use Typst with Python:
# Install GoPdfSuit (includes Typst support)pip install pypdfsuit
# Or install Typst directlypip install typstBasic usage:
import typst
# Direct compilationtypst.compile("document.typ", output="document.pdf")
# Or use GoPdfSuit for template-based generationfrom pypdfsuit import PdfGenerator
generator = PdfGenerator(template={ "elements": [ {"type": "math", "content": "E = m c^2", "syntax": "typst"} ]})generator.render({}, "einstein.pdf")For learning Typst syntax, the official documentation at typst.app/docs has excellent examples.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments