Programmatically generating my CV with Typst

Published 19.01.2025 • Last modified 17.04.2026

It’s the time of year to start sending some summer job applications again. And is there a better way to procrastinate improve the job searching experience than to generate the CV from simple markup with Typst?

Typst is new1 a typesetting system similar to LaTeX, but has much nicer syntax, and also it’s written in Rust!🤷

In this post I’ll show some basic features of Typst to build a simple CV file that looks like this.

Unable to display PDF file. Download instead.

To get started, you can either install the typst CLI or use their online editor, typst.app (both are excellent). If you have the typst CLI installed, you can create a file like cv.typ and compile it with typst compile cv.typ. I highly recommend using the VS Code extension Tinymist Typst as it provides autocomplete, error reporting, formatting and instant previews.

Here’s everything required to make the page header with contact information:

#set page(
  paper: "a4"
)

#set text(
  font: "Inter"
)

#set par(
  spacing: 2em
)

#grid(
  columns: (1fr, 1fr),
  align(left)[
    = John Smith
  ],
  align(right)[
    Phone +123 45678910 \
    #link("mailto:[email protected]") \
    #link("https://my-own.website")
  ]
)

#line(length: 100%, stroke: 1pt + gray)

There are a few rules in the file first, which set the paper size, font family and paragraph spacing. After that there is a “grid” element which allows displaying elements side-by-side. I define two columns that are 1 fraction each. = in front of a line makes it a h1 header, == becomes h2 and so on..

I’m using the Inter font here, you probably need to install the it from here to your system, or use a different font.

Here’s what that looks like:

Unable to display PDF file. Download instead.

Not much content in there yet, but notice how simple the markup really is. And you don’t even need to look up the documentation very often since the VS Code extension has such great autocomplete.

For the sections, it’s possible to define custom elements like this:

#let section(content, title: str) = {
  grid(columns: (1fr, 2.5fr),
    [= #title],
    content
  )
}

#let subheader(content) = text(content, weight: "semibold", size: 1.2em)

They can be used to create sections without duplicating any markup:

#section(title: "Profile")[
    #lorem(50) // 50 words of lorem ipsum
]

#section(title: "Experience")[
	#subheader("Computer programmer") \
	#lorem(60)
]

Very neat!

Some sections of a CV may not be required for all applications. Another useful thing to remember is that whole sections of the file can be commented out:

// #section(title: "Hobbies")[
//   Frolicking, doodling, lollygagging, horsing around
// ]

This means that they will be omitted from the output, but aren’t completely gone from the file. The .typ file can also be checked into a git repository, so that all changes are tracked.

Here’s what the final product looks like, again:

Unable to display PDF file. Download instead.

Download sample cv.typ

  1. Typst is *so new* that Hugo, the static site generator used by this site, was updated to highlight .typ files only 3 days ago in v0.141↩︎