Packages
Typst documents pull in libraries with #import. To resolve them you give the
engine two things:
packagehandler - given(namespace, name, version), return the package's.tar.gzbytes. Called lazily, on import.setRemotePackages- feed an index so autocomplete and bare-version resolution know what exists before any import is written. Optional.
@preview from the public registry
The @preview namespace maps to the official Typst package registry. Wire the
handler to fetch tarballs from it:
Index loading is best-effort: if it fails, imports still resolve through the
package handler - only the autocomplete catalog goes dark. The index decoder
accepts JSON only.
Cache the tarballs. The engine ships indexedDbCache() and withCache():
Private namespaces
setRemotePackages(index, privateNamespaces) takes a second argument - your own
namespaces, each with its own index:
#import "@acme/letterhead:1.0.0" then routes through the same package
handler - branch on namespace there to serve private tarballs from your
backend.
Cross-origin note
Fetching tarballs and the index from a third-party host must pass cross-origin
isolation. If the registry sends CORS but not a Cross-Origin-Resource-Policy
header, serve your app with Cross-Origin-Embedder-Policy: credentialless
instead of require-corp (see Vite & frameworks).