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 # teststypst.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 packageExample 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
- Fork github.com/typst/packages
- Add your package under
packages/preview/PACKAGE/VERSION/ - Open a Pull Request with title
my-package:0.1.0 - Address review comments from the curators
- Wait for merge (usually days to a week)
- After merge,
@preview/my-package:0.1.0is 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 havelatest. Always pin to a specific version.
TypeTeX auto-fetches @preview packages — drop in #import and the package is available immediately. Browse what's on offer at typst.app/universe.
Frequently Asked Questions
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.
[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".
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.
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.
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.
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.
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.
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).
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.