Embracing Typst: My New Foundation for Content Creation

Technology

Discover why I've adopted Typst as my primary content creation tool, replacing Markdown and Org mode, and explore its powerful features for multi-format publishing.

I've fully transitioned to Typst for all my content needs, encompassing my website, videos, and various other projects. My work involves creating technical educational content of diverse lengths, from 30,000-word coursework for clients to an 8,500-word Rust Quickstart document.

This content is distributed across numerous formats and platforms. Some serve as video scripts, while others are published directly to the web, distributed as PDFs or emails, printed and bound, or used in conference presentations.

My recent projects include coursework and articles for Rust Adventure, This Week in Bevy, various client engagements, and content for YouTube and other video platforms.

For a long time, I've sought a writing format that could cater to such a wide array of requirements.

Typst

I first encountered Typst a few years ago around its initial launch, and it has remained on my radar ever since.

Typst has made significant progress in becoming a modern LaTeX competitor, which led me to use it for writing book-length content locally. More recently, its scope has expanded to be more general, positioning itself as "The new foundation for documents." I believe this is an excellent direction.

What do I like about Typst?

To appreciate what I like about Typst, it's helpful to consider the tools I used previously. Most of my writing before Typst was done using Markdown variants and Org mode (yes, I used Emacs much more back then).

Both Markdown and Org mode have compelling aspects. Markdown is both great and terrible due to its simplicity. If you stick to its core features, Markdown is generally acceptable and widely supported. However, it often necessitates custom modifications, and the more modifications you introduce, the less maintainable your content authoring setup becomes.

Org mode is fantastic for many reasons. While nobody would describe Org mode as simple, it offers remarkable interactivity—like opening code blocks in language-specific buffers, executing arbitrary code, capturing information, interlinking, and agenda management.

However, Org mode is largely confined to Emacs and GitHub. It's not a format easily shared or collaborated on with others, nor does it lend itself well to writing outside of the Emacs environment.

Bibliography

Typst inherently supports bibliographies. I conduct extensive research and rely on tools like Zotero to manage it. The inability to cite posts, papers, videos, and other sources without extra effort to embed links was a significant pain point.

Typst supports several bibliography formats, including its own Hayagriva. I can now cite anything in my growing Hayagriva file, such as this page I referenced while writing a post about shaders:

complementary-shaders: type: Misc title: Complementary Shaders | Official Site author: https://github.com/ComplementaryDevelopment date: 2025-11 url: https://www.complementary.dev/shaders/

All my references are tracked and can be automatically included at the end of any post I write from now on.

Document Queries

Typst allows you to query the document, both internally and externally. This means you can query for elements such as:

  • All headings, for a table-of-contents as JSON
  • All codeblocks, for testing or screenshotting
  • Specific metadata, as a frontmatter replacement

Here's an example of using query within a document designed for PDF output. It fetches <frontmatter> metadata defined elsewhere in the document to render a title, byline, and image on the PDF's first page.

#context {
  set text(40pt, font: ("Outfit", "Comic Sans MS"), weight: 900, alternates: true)
  let meta = query(<frontmatter>).at(0).value
  pad(bottom: 16pt,)[
    #box(height: 20%)[
      #image("/assets/" + meta.image_url, width: 100%)
    ]
  ]
  box(height: 30%, width: 100%)[
    #align(center)[
      #meta.title
    ]
    #set text(15pt, font: ("Outfit", "Comic Sans MS"), weight: 400, alternates: true)
    #box(height: 20%, width: 100%)[
      #align(center)[
        #meta.byline
      ]
    ]
  ]
}

To obtain a JSON output of all headings in a document via the CLI, you would use:

typst query main.typ "heading"

Scripting

Typst incorporates a complete scripting language along with features like 'show rules.'

The easiest way to illustrate its utility is by showcasing a custom function I wrote for notes, which previously required special AST support in Markdown.

Here is the output:

note The default note with two paragraphs

tip I'd use a shovel for this, since a fork isn't as effective.

important This is really important

warning danger is near!

caution be careful!

And here is the usage in the Typst document:

#note[
The default note
with two paragraphs
]
#note(level: "tip")[
I'd use a shovel for this, since a fork isn't as effective.
]
#note(level: "important")[
This is really important
]
#note(level: "warning")[
danger is near!
]
#note(level: "caution")[
be careful!
]

The implementation configures itself to adapt to specific output formats. This means it renders the desired HTML for web targets and different layouts when targeting PDFs.

Plugins

With a content format featuring built-in scripting and styling solutions, you can explore Universe, the Typst package registry.

This registry includes excellent packages like zebraw, which offers sophisticated code syntax highlighting, complete with headings, footers, line numbers, and line highlighting.

Multi-Target (HTML, PDF, Slideshow, etc)

I could elaborate extensively on the advantages of a format that can target multiple platforms. You're already reading this in HTML, it's available as a PDF, and I'm currently exploring its use for presentation slides.

PDF Hot Reload?

My websites are typically built using Leptos, and content-heavy sites like Rust Adventure, christopherbiscardi.com, and This Week in Bevy are also built with Islands architecture. This provides a fully functional, modern frontend framework deployable as a client-side web app, a static site, or a full-stack server/client hybrid. Islands also minimizes the WASM payload.

While hot-reloading for websites is always available, sometimes a non-site-specific content authoring workflow is beneficial.

Typst includes its own PDF and HTML target hot-reload server. This allows me to write, save, and instantly view changes within milliseconds, regardless of the final content destination.

The Downsides

It's not entirely perfect, and it might not be suitable for everyone right now. I write extensively and require a format that can keep pace. Therefore, I'm willing to be an early adopter, even for the experimental HTML target, and encounter occasional issues. Most users might prefer to wait for the HTML target to stabilize.

Experimental HTML Target

The HTML target is experimental and carries clear warnings about its incompleteness, advising against production use.

Whoops.

I've always been an early adopter. I'm confident in my nearly decade of Rust skills, almost two decades of web development experience, and my ability to address any issues within Typst if absolutely necessary 1.

Since I'm an early adopter of the HTML target, there are issues to navigate.

My ever-growing lib.typ?

I'm not entirely sure if this is a true downside, but I've adopted the practice of storing all customizations in a lib.typ file. This file then manages various needs like large-scale layout, target-specific rendering (PDF/HTML/etc.), bibliography inclusion, and provides functions for rendering, such as this note function:

note This is a note that can come in a variety of flavors.

#note[
This is a note that can come in a variety of flavors.
]

Stability?

Typst isn't guaranteed to maintain stability at the rapid pace I wish to use it. The format isn't "locked in" like the CommonMark specification, and it offers much more functionality.

That said, I've reviewed the migration guides and worked through a few of them. I'm comfortable with the potential workload of migration, considering the substantial benefits I gain from using the format.

References

Using a single bibliography across all documents (including HTML targets) is an efficient way to manage a single file rather than many. The HTML target output uses #loc-1 format IDs by default, which can be customized using reference syntax:

=== References <references>

This is generally fine, but it introduces a potential vulnerability for breaking older posts when adding to my bibliography library, as reference names share the same namespace. To mitigate this, I prefix my bibliography IDs with bib:, for example, bib:mytopic.

I've filed an issue regarding this.

Typst for Everything?

Yes, Typst is now my top choice for a writing format, and I'm progressively integrating it into more and more areas. For me, it powers:

  • Video scripts, and the generation of code blocks from those scripts
  • HTML platforms, primarily websites... but also email?
  • HTML-targeted outlines via heading queries, etc.
  • PDF construction for email and print

There are still areas where I haven't quite fit it in yet. I need to evaluate if it's a suitable replacement for creating slides for conference talks.

And it probably doesn't make sense to replace Markdown for the small descriptions of each project on This Week in Bevy. Well, maybe. We'll see.

I still have some integration work ahead, but I'm very enthusiastic about the future of Typst at the moment.

References

  1. C. Biscardi, "Typst: The LaTeX alternative in Rust - YouTube." [Online]. Available: https://www.youtube.com/watch?v=sWmlbMh3ol8
  2. https://github.com/ComplementaryDevelopment, "Complementary Shaders | Official Site." [Online]. Available: https://www.complementary.dev/shaders/

Footnotes

  1. Recruiters, I've finally surpassed a decade of working with React, lol.