Typst Guide

Typst Package Creation

Build a package with typst.toml and lib.typ. Test in @local. Publish to @preview (Typst Universe) via PR.

Package structure

my-package/
├── typst.toml          # manifest
├── lib.typ             # entrypoint (default name)
├── README.md           # documentation
├── LICENSE             # license file
├── examples/
│   └── basic.typ       # usage examples
└── tests/
    └── test-basic.typ  # tests

typst.toml manifest

[package]
name = "my-package"
version = "0.1.0"
entrypoint = "lib.typ"
authors = ["Your Name <you@example.com>"]
license = "MIT"
description = "A short, clear description of what this package does"
homepage = "https://github.com/yourname/my-package"
repository = "https://github.com/yourname/my-package"
keywords = ["academic", "papers", "templates"]
categories = ["templates"]
exclude = ["tests/**", "*.png"]    # files to exclude from package

Example package: a custom callout block

// lib.typ
#let callout(body, kind: "info") = {
  let colors = (
    info: (rgb("#e3f2fd"), rgb("#1976d2")),
    warning: (rgb("#fff8e1"), rgb("#f9a825")),
    danger: (rgb("#ffebee"), rgb("#c62828")),
  )
  let (bg, fg) = colors.at(kind)
  block(
    fill: bg,
    stroke: 1pt + fg,
    inset: 8pt,
    radius: 4pt,
    body,
  )
}

#let info(body) = callout(body, kind: "info")
#let warning(body) = callout(body, kind: "warning")
#let danger(body) = callout(body, kind: "danger")

Test locally with @local

# Install to local namespace
# Linux/Mac:
mkdir -p ~/.local/share/typst/packages/local/my-callouts/0.1.0
cp -r my-package/* ~/.local/share/typst/packages/local/my-callouts/0.1.0/

# Windows:
# %APPDATA%\typst\packages\local\my-callouts\0.1.0\

# Now use in any document
#import "@local/my-callouts:0.1.0": *

#info[Standard info note]
#warning[Watch out!]
#danger[Critical issue]

Publishing to @preview

  1. Fork github.com/typst/packages
  2. Add your package under packages/preview/PACKAGE/VERSION/
  3. Open a Pull Request with title my-package:0.1.0
  4. Address review comments from the curators
  5. Wait for merge (usually days to a week)
  6. After merge, @preview/my-package:0.1.0 is publicly available

Bumping versions

Each version is a new directory. To release 0.2.0:

  • Update version = "0.2.0" in typst.toml
  • Submit PR adding packages/preview/PACKAGE/0.2.0/ (don't modify 0.1.0 — old versions stay available)
  • Users pinned to 0.1.0 keep working; users pinned to 0.2.0 get the new version

Common mistakes

  • Mutating a published version. Once 0.1.0 is published, it's frozen. Bump to 0.1.1 for any change.
  • Missing license file. Required by curators. Even for permissive licenses, include a LICENSE file.
  • Functions exported but not documented. Curators expect a README explaining the public API.
  • Pinning to latest. Typst doesn't have latest. Always pin to a specific version.
Browse Typst packages

TypeTeX auto-fetches @preview packages — drop in #import and the package is available immediately. Browse what's on offer at typst.app/universe.

Try TypeTeX free

Frequently Asked Questions

What's the structure of a Typst package?

A folder containing typst.toml (manifest) and the entrypoint .typ file (typically lib.typ). For local packages: ~/.local/share/typst/packages/local/PACKAGE/VERSION/. For published packages: same structure submitted to github.com/typst/packages.

What goes in typst.toml?

[package] section with name, version, entrypoint, authors, license, description. Optional: keywords, categories, repository URL, exclude. Example: name = "my-cv", version = "0.1.0", entrypoint = "lib.typ", authors = ["Your Name"], license = "MIT", description = "A modern CV template".

How do I test a package locally?

Install to ~/.local/share/typst/packages/local/PACKAGE/VERSION/ (or %APPDATA%\typst\packages\local\PACKAGE\VERSION\ on Windows). Then in any document: #import "@local/PACKAGE:VERSION": *. Edit lib.typ, save, recompile — changes appear immediately. Local packages are for personal use; @preview is for publication.

How do I publish to @preview (Typst Universe)?

Fork github.com/typst/packages, add your package directory under packages/preview/PACKAGE/VERSION/, submit a PR. The community curators review for: (1) the package builds, (2) typst.toml is well-formed, (3) license is permissive, (4) doesn't duplicate existing functionality, (5) basic quality checks. Approval takes days to weeks.

What versioning convention does Typst use?

Semantic versioning (semver): MAJOR.MINOR.PATCH. 0.x means unstable; 1.0+ implies stable API. Each version is its own folder — old versions remain available. Users pin specific versions: #import "@preview/foo:0.2.1": *. Bumping a version requires a new directory.

What's a template package vs a regular package?

A template package provides starter content for new projects (CV templates, thesis templates, paper templates). It includes a template/ directory with example files. Users init via 'typst init @preview/PACKAGE' which creates a new project with the template files. Regular packages just provide functions/utilities.

What license should I use for my Typst package?

MIT or Apache 2.0 are most common — permissive, allows commercial and academic use. Public domain (Unlicense, CC0) is also accepted. Restrictive licenses (GPL, LGPL) are allowed but make it harder for others to compose your package with theirs. For typesetting/academic packages, MIT is the safe default.

Can I import private GitHub repos as packages?

Not directly via #import. Workaround: clone the repo locally, place under @local namespace. Or vendor it into your project's directory and #import via relative path. Typst doesn't yet have private package registry support — only @preview (public) and @local (your machine).

How does Typst's package system compare to LaTeX's?

Typst packages: typed, semver, simple manifest, auto-fetched from @preview. LaTeX packages: ad-hoc, distributed via TeX Live / CTAN, complex global install, no version management at the document level. Typst's approach is closer to npm or cargo than to traditional LaTeX.

More Typst guides