Hi all. Typst is great, but I cannot figure out how to work well with a project that uses #include files. I have a main.typ, that includes several chapter or section files.
The problem: I open “main.typ”, and everything looks great. If I open one of the chapter files and I get errors, such as “the document does not contain a bibliography”. Obviously it is trying to compile the document on its own, rather than as an included file in main.typ.
Where it occurs: This occurs in neovim (with a standard typst setup). It also occurs in Edist (a native mac app for editing typst). I assume this happens in other editors too.
When I search online about this I see solutions for vscode for “pinning” the main file (using Tinymist). But this seems like the wrong place to solve this problem, as this only cures the issues for those using tinymist.
The question: So, is there a way to solve this in typst? If not, why not? Should I open a feature request?
Would you mind posting a stripped down example that generates the error message please. I suspect this discussion will raise awareness of any idiosyncrasies that can arise with multi-file documents.
Indeed, it would be good to be able to pin the root file from the typst file instead of the editor. In neovim, the workaround that I found is to add a file named “.typstroot” at the root directory (containing the main file), and a script in the “opts” of my typst-preview plugin to set the root as the closest parent containing .typstroot. Here is the script :
‘’’
get_root = function(path_of_main_file) --the root is the parent containing a file with name .typstroot
local root = os.getenv("TYPST_ROOT")
if root then
return root
end
local path = vim.fn.expand("%:p:h") -- Start from current file's directory
while path and path ~= "/" do
if vim.fn.filereadable(path .. "/.typstroot") == 1 then
return path
end
path = vim.fn.fnamemodify(path, ":h") -- Go up one directory
end
return vim.fn.fnamemodify(path_of_main_file, ":p:h")
end,
‘’’
This is not ideal but at least I have to modify my config only once.
= Included chapter
This citation works when `main.typ` is compiled: #cite(<typst>).
references.bib
@misc{typst,
title = {Typst: Compose papers faster},
author = {{Typst GmbH}},
year = {2026},
url = {https://typst.app}
}
Compiling the main file succeeds:
typst compile main.typ
Compiling the included file directly fails:
typst compile chapter.typ
error: the document does not contain a bibliography
┌─ chapter.typ:3:50
│
3 │ This citation works when `main.typ` is compiled: #cite(<typst>).
│ ^^^^^^^^^^^^^
Typst already has a TOML file for some configuration purposes.
This looks like the right place to add a section for defining the main file.
And it would be in line with the way other multi-file projects such as Rust or Python define things.
However, it would be good to be able to specify multiple different targets. So for example, I will often have a draft main file which includes extra notes than the final main file.
@vmartel08 And yet I believe this is the correct solution to the problem that the good @brettc is trying to solve. The real problem is that chapter.typ cannot resolve a citation because no bibliography file is available to it when compiled standalone.
Hmmm, update. The fix leaves us with an empty bibliography. I’m so confused. The more I learn the less I know.
I can also see a bunch of use cases for document metadata; right now typst.toml is only for packages, if there is a compelling use case for document manifests, there seems to be openness for it. I think editors could already look for a typst.toml file and look for tool.editor.main-file = ...; that may be an alternative to .typstroot that multiple editors could more easily standardize on.
Edit:
I want to explicitly address this as well, because I was just about to tag this tooling.
Tinymist has this feature, but I think it is ultimately up to editors to implement something like this. Ideally, we can make sure that there is one convention (see above) that all editors could follow.
Why do I think it’s tooling specific? Because choosing the main file is (already) done in the editor:
Web app: use the “eye” icon
CLI: provide an argument
Tinymist: pinning, or starting a preview
Typst could add an option to compile a typst.toml that contains the metadata, but unless that was a core feature in the compiler, the thing that is compiled is a Typst file, and editors must choose by themselves which file is the entry point.
I think there’s place for a feature request (the typst.toml file could also define what compiler options to use, e.g. font path, etc.) but for main file alone, I think a [tool] section would be enough and the feature would not be considered to carry its weight.
Yes, this is the main reason for raising the issue. If everyone downstream of typst implements their own solution, this becomes a mess. Best do it once in typst.
I read the some of the responses above as saying something like: “Well, if you are trying to compile the chapter.typ, then the output is correct!”. And I agree.
The problem is that when I’m editing that single file in neovim (or whatever), neovim needs a way to know that what it should really be compiling is the master file. Perhaps something like ‘typst compile chapter.typ --target main’
where ‘main’ needs to be defined in the toml file? So…
[project.targets.main]
main = "thesis.typ"
[project.targets.slides]
main = "slides.typ"