Is there a way to programmaticaly generate documents?

I want to use typist to generate PDF reports programmaticaly.

Currently, I have a jinja template, that I populate with results from the database, but this workflow is very annoying. I would like to create a service that serves pdf and eventually send the PDF by email.
I have seen posts online similar to my goal, but no concrete examples.

Ideally I would like to run everything in python if possible.

1 Like

You can use a similar process to what you already have with jinja templating. In fact, you could even use jinja to create a typst document rather than whatever document format you are using right now (I assume you’re doing HTML then converting to PDF).

So, if for example:

<h1>{{ some_heading }}</h1>
<p> Some {{ some_value }} </p>

You’d convert that to

= {{ some_heading }}
Some {{ some_value }}

and so on.

You would then

  1. populate the template with values,
  2. output a temporary typst file
  3. use subprocess and convert it to PDF using typst compile.
  4. delete the temporary file (if need be)
  5. serve the PDF

The bottom line is that you are producing a string, writing it to file, and using typst to convert it. There are multiple ways to produce that string, jinja being one of them (and not a bad option imo).

Currently, I have a jinja template, that I populate with results from the database, but this workflow is very annoying. I would like to create a service that serves pdf and eventually send the PDF by email.

What about it is annoying? keep in mind that Typst natively supports reading various data formats (see Data Loading – Typst Documentation), so you can load them from within Typst directly and use the familiar #var syntax for displaying values.

Ideally I would like to run everything in python if possible.

You’re in luck, there’s typst · PyPI

2 Likes

While you can use a templating engine like Jinja, personally I would suggest moving the templating to Typst itself. The mixing of markup and code that Typst allows is designed to support exactly that. The post Can I configure my document (e.g. draft/release version, light/dark theme) when creating a PDF without modifying the Typst file directly? imo covers this topic (“rendering different data, serial letter style”)

Combine data loading with a Python library like the one @Tinger mentioned, this should get the job done.

2 Likes

Before Typst I used the Python ReportLab library for a few jobs and it worked really well, or at least I could precisely overlay text elements as a second layer atop a pre-designed PDF, and match the house style perfectly (assuming I measured the designer’s dummy document accurately in Illustrator to get the right co-ordinates :) )

These days I’d prefer an all-Typst workflow, at least for laying out the body of the page. Pre-made, print-ready elements (headers/footers/backgrounds in vector format, etc) I’d incorporate by overlaying on an existing ‘background’ PDF. Afaik Typst doesn’t do this yet but it should be possible with a script that invokes Typst then a Python library that can overlay PDFs (PyPDF2 ?).

To synthesize @Tinger and @SillyFreak with the suggestion of the typst library, here is a simple hello world example in case someone is looking in the future:

In helloworld.typ:

= Hello world

#sys.inputs.at("some_value")

In helloworld.py:

import typst  # using v0.11.1

# sys_inputs must be a dictionary of type string:string
sys_inputs: dict[str, str] = {"some_value": "hello world"}

typst.compile(input="helloworld.typ", output="helloworld.pdf", sys_inputs=sys_inputs)

The benefit of this method is that you could more easily compose your typst template (i.e. via the website).


:eyes: However, a limitation seems to be in what you can pass to the template (dictionary of key:value, but both are limited to string type). That likely means that, for example, if you want to pass a tuple of values from a database query, it would have to be converted to string, then in the typst template you would have to convert to a typst-native type.

So, if you need more versatility in objects, you may need to do string templating of some variety within python (i.e. jinja, or string templates, etc).


Update:

Based on @SillyFreak’s comment below, here is another example passing JSON data:

In json_example.py:

import typst
import json

# convert your data to string with json.dumps
data = json.dumps([1, 2, 3, 4, 5])

sys_inputs: dict[str, str] = {"data": data}
typst.compile(
    input="json_example.typ", output="json_example.pdf", sys_inputs=sys_inputs
)

In json_example.typ:

#let values = json.decode(sys.inputs.data)

#for value in values [
  #value #linebreak()
]
2 Likes

Actually for that case, you could use JSON or one of the other formats supported by Typst (and Python). Using templating (and then parsing in Typst) for that purpose should not be necessary:

(feel free to incorporate that into your response, so that it can be the canonical complete one)

1 Like

Nice! I didn’t know about that. I’ve updated my comment.

1 Like

My advice is similar to others: try to make as much as you can with Typst. In my case, toml files have been of help to “configure” the document and some analysis and csv files for data.

Sadly, this is not always the case so you should rely on another language. Maybe your analysis depends a lot on python and the Typst part is simple. In my case, I have a software which rely on dates types, datafarmes, etc, which are not so advanced in Typst so I coded it in Julia. Then, with Typstry.jl and TypstJlyfish.jl you can compile with Typst_jll and embed julia code in your typst files. (video about Jlyfish). Even though is julia, it can help to understand the process.

1 Like

Thank you for all of the insights.

I will definitely try it with the python package and a .typ file.

Will comeback to share my results, but it won’t be anytime soon.

Hi, for the time being and for the benefit of other readers, I have marked @Daniel’s response as the accepted answer. Feel free to change that if your attempts eventually make you conclude that another answer works better :slight_smile:

It is perfectly doable, Typst is awesome for this specific usecase!
I have created several hundred-pages technical user manuals using (almost) pure Typst.

I have a large-ish private software project whose components are described by about 500 JSON files, one each.
Different versions of the system combine the components in different way, and for each I needed to generate a different technical manual.

All the basic data is fetched from JSON; the only thing I had to do outside of Typst is to create a index of such JSONs before compilation, because Typst misses a “does-file-exist?” functionality.

The Typst code is about 2000 lines, including JSON caching, a small plotting library based on CeTZ, and custom .typ description for a bunch of special components (e.g. some that needed special charts and explanation).

It is beautiful, reproducible, git-friendly, and easy to maintain!

2 Likes