Written by Bjørn Erling Fløtten, Trondheim, Norway. Updated 27 Apr 2026.
License: CC BY 4.0.
This article demonstrates scope in typst through 10 practical examples (zip file). It applies to typst version 0.14.2 (b33de9de). Typst is a markup-based typesetting system designed as an alternative to LaTeX
The TL;DR is that you can not make global imports (issue 595) and neither can you literally input files (issue 4194). Both of these issues are "Closed as not planned" because they go against the core design of typst.
The solution is simply to repeat imports wherever needed. This is demonstrated in the final example (Ex 10)
Below we explain our process at work trying to understand this (before we finally ended up with the aforementioned conclusion).
Background: We wanted to apply a consistent formatting throughout the document, and also to make variables and functions available globally. The issue was complicated by the fact that our document has multiple simultaneous versions, three levels of inclusions (top level, chapter, sub chapter) and a mix of autogenerated and manually written text.
We got distracted by attempting to accomplish two things at the same time: Use a template and also import variables and functions. The template syntax can also be a bit difficult to grasp. The 10 examples below are an attempt at clarifying all this. You can download the zip file for experimenting locally.
Go to TL;DR for the final working example which also works for sub chapters. The solution was simply to repeat imports wherever they are needed and to not mix up template import with variable and function import.
Defining formatting, variables and functions together with the text in the same document works as expected.
#show heading.where(level: 1): set text(size: 30pt)
#set page(
header: [
My header
],
)
#let MY_VARIABLE = "My variable"
#let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
[#text]
)
}
= My heading with size 30pt
This page has the header "My header" at top
#MY_VARIABLE
#warning([My warning])
Result: main.pdf
Trying to split out formatting to a separate file causes problems. This is somewhat expected. What we define in an include file should not be present in the scope of the main file.
#show heading.where(level: 1): set text(size: 30pt)
#set page(
header: [
My header
],
)
#let MY_VARIABLE = "My variable"
#let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
[#text]
)
}
#include "include.typ" = My heading // Non-resolving reference #MY_VARIABLE // Non-resolving reference #warning([My warning])
Result: Not available.
The sample below compiles but note that "nothing" gets included from the include file, not even page setup or headers
#show heading.where(level: 1): set text(size: 30pt)
#set page(
header: [
My header
],
)
#let MY_VARIABLE = "My variable"
#let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
[#text]
)
}
#include "include.typ" = My heading with wrong size This page has no header on it. // Non-resolving reference // #MY_VARIABLE // Non-resolving reference // #warning([My warning])
Result: main.pdf.
Including files in the "opposite" manner does not compile either. That is, having formatting in the main file and include the text does not compile. This was (for us at least) the surprising part because now the text part is hierarchically "below" the main file. One could naïvely expect that "everything" in the main file carries through to the included files but it does not.
#show heading.where(level: 1): set text(size: 30pt)
#set page(
header: [
My header
],
)
#let MY_VARIABLE = "My variable"
#let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
[#text]
)
}
#include "include.typ"
= My heading // Non-resolving reference #MY_VARIABLE // Non-resolving reference #warning([My warning])
Result: Not available.
Including files in the "opposite" manner works for the "show heading" and "set page" though. But "MY_VARIABLE" and "warning" do not resolve.
#show heading.where(level: 1): set text(size: 30pt)
#set page(
header: [
My header
],
)
#let MY_VARIABLE = "My variable"
#let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
[#text]
)
}
#include "include.typ"
= My heading with size 30pt This page has the header "My header" at top // Non-resolving reference // #MY_VARIABLE // Non-resolving reference // #warning([My warning])
Result: main.pdf.
Using #import as template brings us closer to a solution. See Ex 7 for a partly working example.
#let MyTemplate(body) = {
show heading.where(level: 1): set text(size: 30pt)
set page(
header: [
My header
],
)
let MY_VARIABLE = "My variable"
let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
[#text]
)
}
body
}
#import "include.typ":MyTemplate #show: MyTemplate // The "body" parameter to the Template function is implicitly // understood to be everything from here and below = My heading with size 30pt This page has the header "My header" at top // Non-resolving reference #MY_VARIABLE // Non-resolving reference #warning([My warning])
Result: Not available.
If we do not reference "MY_VARIABLE" and "warning" then the code compiles. But then we are back to what we accomplished in Ex 6.
#let MyTemplate(body) = {
show heading.where(level: 1): set text(size: 30pt)
set page(
header: [
My header
],
)
let MY_VARIABLE = "My variable"
let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
[#text]
)
}
body
}
#import "include.typ":MyTemplate #show: MyTemplate // The "body" parameter to the Template function is implicitly // understood to be everything from here and below = My heading with size 30pt This page has the header "My header" at top // Non-resolving reference // #MY_VARIABLE // Non-resolving reference // #warning([My warning])
Result: main.pdf.
We can define "MY_VARIABLE" and "warning" separately in the include file and import them separately.
#let MyTemplate(body) = {
show heading.where(level: 1): set text(size: 30pt)
set page(
header: [
My header
],
)
body
}
#let MY_VARIABLE = "My variable"
#let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
text
)
}
#import "include.typ":MyTemplate, MY_VARIABLE, warning #show: MyTemplate // The "body" parameter to the Template function is implicitly // understood to be everything from here and below = My heading with size 30pt This page has the header "My header" at top #MY_VARIABLE #warning([My warning])
Result: main.pdf.
The last example does not work if we introduce a typst file for each chapter though. This is similar to what was demonstrated in Ex 4 so it should not come as a surprise.
#let MyTemplate(body) = {
show heading.where(level: 1): set text(size: 30pt)
set page(
header: [
My header
],
)
body
}
#let MY_VARIABLE = "My variable"
#let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
text
)
}
#import "include.typ":MyTemplate, MY_VARIABLE, warning #show: MyTemplate // The "body" parameter to the Template function is implicitly // understood to be everything from here and below #include "chapter1.typ"
= My heading with size 30pt This page has the header "My header" at top // Non-resolving reference #MY_VARIABLE // Non-resolving reference #warning([My warning])
Result: Not available.
The final solution is to repeat the import whenever needed and to not mix up template import with variable and function import.
#let MyTemplate(body) = {
show heading.where(level: 1): set text(size: 30pt)
set page(
header: [
My header
],
)
body
}
#let MY_VARIABLE = "My variable"
#let warning(text) = {
rect(
fill:(rgb("#fdba74")),
radius: 4pt,
text
)
}
#import "include.typ":MyTemplate #show: MyTemplate // The "body" parameter to the Template function is implicitly // understood to be everything from here and below #include "chapter1.typ"
#import "include.typ":MY_VARIABLE, warning = My heading with size 30pt This page has the header "My header" at top #MY_VARIABLE #warning([My warning])
Result: main.pdf.
So the conclusion is simply to repeat an import wherever it is needed.
Final hint: If you would like to organize the chapters into subfolders you might have to use to "--root" argument to "typst compile" in order for typst to accept including files from "above" the chapter folder.
Contact: