Crash course
Note
The official Typst documentation website has its own tutorial, which goes into much more depth than the crash course you're actually reading. Here, we'll focus on giving you the big picture rather than technical details.
Typst = text + a compiler¶
What we call "Typst" is usually one of the following:
- the Typst company the legal organization and people developing Typst
- the Typst typesetting system the language itself
- the Typst compiler the (CLI) program that actually creates the PDF
The compiler will take a .typ file and create a PDF file with it. For example, a Typst file might look like this:
#set page(fill: red, width: 10cm, height: 3cm)
== Here goes the title...
Hey folks, how's that crash course going so far?
Then we run typst compile file.typ, and we get:

Typst, in practice¶
The compiler is a CLI (Command Line Interface), which means it needs to run from the terminal.
But when you're trying to use Typst in more complex environments, like a web server or data pipeline, you're often interested in generating a PDF from a programming language, not from the terminal.
Once you'll understand the basics of Typst, you'll learn how to use Typst from a programming language.
Basic syntax¶
If you've ever used Markdown before, getting started with Typst will be easy. For example, the following Typst file:
#set page(fill: rgb("#f2e9e4"), width: 12cm, height: 5cm)
= My first Typst document
== Smaller heading
=== But still a heading
This is a paragraph, where text can be *bold*, _italic_, or `code-like`.

Functions¶
Typst offers tons of functions that we can use to customize the output of our PDF. The syntax is very simple, and often, very intuitive.
For example, I want to put a blue circle next to a green rectangle, next to red text. How can I do that?
#set page(fill: rgb("#f2e9e4"), width: 12cm, height: 5cm)
#stack(
dir: ltr, // direction --> left to right
spacing: 0.5cm, // space between elements
circle(fill: blue, width: 2cm),
rect(fill: green, width: 3cm),
text(fill: red, "Hello")
)

What if I want them to be vertically aligned? I just call the align() function:
#set page(fill: rgb("#f2e9e4"), width: 12cm, height: 5cm)
#align(horizon, stack(
dir: ltr,
spacing: 0.5cm,
circle(fill: blue, width: 2cm),
rect(fill: green, width: 3cm),
text(fill: red, "Hello"),
))

Set rules¶
A set rule is a way to tell Typst how a given function should behave. For example, by default the text() function uses fill: black for its color, but if we do:
Then all text will be blue. You might realize that this is what we used in the examples before with:
This says that the page() function (which is used to create every page under the hood!) has a width of 12cm and a height of 5cm.
Variables¶
We can define variables, like in any programming language, in order to reuse them thanks to the let keyword. A common use case is to define branding colors:
#let yellow = rgb("#FFC300")
#let purple = rgb("#421173")
#set page(fill: yellow, width: 12cm, height: 5cm)
#align(horizon, stack(
dir: ltr,
spacing: 0.5cm,
circle(fill: purple, width: 2cm),
rect(fill: purple, width: 3cm, circle(fill: yellow, width: 1cm)),
))

Create your own functions¶
Even though Typst is a markup language (!= programming language), it embeds a scripting language that lets us add logic (if/else statements, for loops, etc.) and create reusable components.
Let's look at an example:
#set page(fill: aqua, width: 12cm, height: 5cm)
#let say-hello(s)= {
// s is the argument name
[Hello my friend #s, how are you?]
}
#say-hello("Joseph")
#say-hello("Justine")

Once again we use the let keyword, and then we wrap the output of the function inside curly braces.
When or when not to use the # symbol¶
A thing that might be confusing in the previous code snippets is that sometimes we use the # symbol, and sometimes we don't.
In the first case, the output is just a simple circle, while in the second case, it's the actual text instead of a circle. Why is that?
It's because Typst has 2 modes:
- Markup mode
- Code mode
By default we're in Markup mode, and we need to add the # before a function name, a set rule or when defining a new variable. But we switch to code mode in many cases:
Those are just common examples, but in practice you'll quickly find this intuitive as you start using Typst. A great way to make this simpler for you is to enable syntax highlighting in your editor. If you have a second look here, you'll see that in the second case the text is all black, meaning that it will be rendered as is.
Exercises¶
Note
- Make sure to either install Typst or use their web app
- Always include
#set page(fill: rgb("#f9f6f4"), width: 12cm, height: 5cm)at the top of the document to:- ensure a fixed page size, because by default it will be A4, which is more than necessary
- have a distinct background (light grey)
1 - Basics¶
Reproduce the PDF below:
2 - A first shape¶
Reproduce the PDF below:
3 - Layout with stack¶
Reproduce the PDF below:

- Use
stack()withdir: ltr - Add
spacingbetween elements - Put a
circle(), arect(), and atext()inside - Look at the
radiusargument instack()and thesizeargument intext()
4 - Variables and set rules¶
Reproduce the PDF below:

- Define the main color (#e76f51) with
#let - Use
#set text(...)to style all text at once
5 - Combining align and stack¶
Reproduce the PDF below:

- Wrap your content in
align(horizon, ...) - Build one vertical stack and small horizontal stacks inside it
- Reuse the same pattern for 3 status lines
#set page(fill: rgb("#f9f6f4"), width: 12cm, height: 5cm)
#align(horizon, stack(
spacing: 0.2cm,
stack(
dir: ltr,
spacing: 0.3cm,
circle(fill: rgb("#2a9d8f"), width: 0.7cm),
text(fill: rgb("#2a9d8f"), "Ready"),
),
stack(
dir: ltr,
spacing: 0.3cm,
circle(fill: rgb("#e9c46a"), width: 0.7cm),
text(fill: rgb("#e9c46a"), "Pending"),
),
stack(
dir: ltr,
spacing: 0.3cm,
circle(fill: rgb("#e76f51"), width: 0.7cm),
text(fill: rgb("#e76f51"), "Blocked"),
),
))
6 - Create a function with parameters¶
Reproduce the PDF below:

- Define
badge(...)with#let - Give it at least 2 parameters (
label,color) - Add one optional parameter with a default value
- Call the function multiple times with different arguments
#set page(fill: rgb("#f9f6f4"), width: 12cm, height: 5cm)
#let badge(label, color, icon: "*") = {
rect(
fill: color,
radius: 5pt,
inset: (x: 10pt, y: 6pt),
text(fill: white, [#icon #label]),
)
}
#stack(
dir: ltr,
spacing: 0.35cm,
badge("Draft", rgb("#6c757d")),
badge("Review", rgb("#f77f00"), icon: "!"),
badge("Done", rgb("#2a9d8f"), icon: "+"),
)
Next step¶
You now have some good Typst foundations! If you want to learn more, you can have a look at this unofficial Typst Examples Book.
Otherwise you're ready to start using Typst from a programming language!



