CLI tool
Myriad-Dreamin/typst.ts avatar
Myriad-Dreamin/typst.ts

typst.ts and the route from a Typst document to a browser page

Run Typst in JavaScriptWorld.

1,243 stars86 forksTypeScriptApache-2.0

At a glance

What is it?
typst.ts compiles Typst documents inside a JavaScript runtime by implementing the typst::World interface and shipping several exporters, and it offers three deployment shapes from static SVG embedding to a fully client side canvas renderer. The interesting part is the intermediate vector format, and the awkward part is that the all in one bundle still fetches its fonts from the network.
Who is it for?
Adopt typst.ts if you want Typst rendering in a browser or a JavaScript service, especially if you want the document to be rendered client side for interactivity or to be served from a static site without a Rust toolchain on the server. Do not adopt it if you only need a PDF or SVG on the server, since the native Typst toolchain already does that without a WASM payload, and treat the release candidate numbering as a signal that the API is still moving.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The same document, three ways through the pipeline

typst.ts is a project dedicated to bringing the power of Typst to the world of JavaScript. In short, it provides a typst::World implementation and several exporters to help compile and render a Typst document, typically inside a browser environment, and it documents the data flow as a collaboration between a server and a browser.

The three forms it presents are the clearest way to understand the design.

Form 1 renders to SVG at server side and then embeds it as a high quality vectored image into HTML files statically. That is the traditional static site output, and it is the form that needs nothing from the client.

Form 2 preprocesses to a vector format artefact at server side and renders it at client side, in the browser. The artefact is what makes this form different.

Form 3 compiles the document at client side and manipulates a canvas element at client side. Nothing about the document is rendered on a server, and the page behaves like a live editor rather than a picture of a document.

The audience is anyone who has a Typst document and a JavaScript delivery problem. A blog that wants its maths rendered without a Rust toolchain in the build, an online book, a web application that wants to show a generated diagram next to a live form, a static site generator plugin. The project lists its own consumers, the shiroa tool for online books in pure Typst, the typst-preview extension for VS Code, the hexo-renderer-typst plugin for the Hexo blog generator, and a vite-plugin-typst, and it publishes renderer and component libraries for JavaScript, React and Angular.

The vector format is the actual invention

The README is explicit that the vector format in Form 2 was developed specially for Typst documents, and that it has several fancy features of its own.

The reason a separate format is needed is that neither of the other two forms can be both static and interactive. An SVG embedded in a page is a finished picture. A canvas rendered in the browser is live, but the server has to have compiled the document to know what to draw, and the canvas path in Form 3 does the compiling client side, which means shipping the compiler to every visitor.

The vector artefact sits between the two. The server compiles once and produces a compact bundle of data for different theme and screen settings, with the bundle size optimised for Typst documents, and the client renders from that bundle. The document stays static in the sense that the client is not compiling, and it stays responsive in the sense that the artefact carries what is needed to redraw at a different width or with a different theme.

Three uses of that artefact are described. Static but responsive rendering, where a compressed artifact holds data for different theme and screen settings, is what the shiroa book tool and the hexo renderer use. Incremental server-side rendering, where a compiler service streams the artefact and the page renders incrementally, is what the VS Code preview uses. And serverless client side rendering, where the whole document runs in the browser like typst.app, is what the single file example and its deployed demo do.

For a team, the decision is a question about where you want the work to happen. Server side keeps the client light and the output reproducible. Client side keeps the deployment trivial and the page interactive. The artefact form is the compromise that lets the server do the expensive part once and the client do the rest.

Installing three ways, and a bundle that needs the network

There are three installation paths, and they are separated by what you are actually installing.

The command line tool is a Rust crate installed from the repository itself, not from crates.io:

bash
cargo install --locked --git https://github.com/Myriad-Dreamin/typst.ts typst-ts-cli

The locked flag and the git source are there for a reason. The README explains that the Rust crates are not published on crates.io yet, since the project has a git dependency on Typst, so there is no registry version to install and the build is pinned to a commit rather than to a version number. The alternative is to download the latest release artefact from the GitHub releases page.

The JavaScript side is on npm, and the packages are layered. The core wrapper library is @myriaddreamin/typst.ts, with a React library at @myriaddreamin/typst.react and an Angular library at @myriaddreamin/typst.angular, and two internal WASM modules behind them, the web compiler and the renderer. There is also a Rust compiler library, reflexo-typst, and the CLI as a library.

The all in one bundle is the one that needs a caveat, and the README puts it in the minimal example rather than in a footnote. By default all-in-one.bundle.js downloads the font assets from GitHub in the browser, so you need to connect to the Internet. A page that is supposed to render a document offline therefore needs the fonts handled separately, and that is the kind of detail that decides whether the single file deployment model works for you.

The minimal example itself is a plain HTML page with a script module loaded from a CDN and a listener that runs the compile once the module has loaded, which is a fair indication of the whole integration story: a script tag and a promise.

The Rust workspace is a conversion pipeline

The Cargo workspace is large and it is arranged as a set of conversions, which is the clearest way to read the project.

The crates/reflexo crate and crates/reflexo-typst sit at the core, and then there is a family of crates under crates/conversion: typst2vec produces the vector format, typst2hast produces a HTML AST, and vec2canvas, vec2dom, vec2svg, vec2sema and vec2bbox each turn the vector format into a different target. A canvas, a DOM tree, an SVG, a semantic tree and a bounding box are five renderers over one intermediate representation, and that is why the vector format had to be designed rather than reused.

The workspace also contains the JavaScript package sources under packages/, the CLI under cli/, a development server under server/dev, fuzzing harnesses under fuzzers/, a benchmark in benches/, and a set of test crates under tests/ covering common, heap profile, incremental, std and docs. The workspace excludes the projects/ directory, which holds the integrations such as the hexo renderer and the vite plugin, and those are built separately by the JavaScript side.

The dependency versions are pinned tightly to the Typst release, with typst, typst-eval, typst-ide, typst-pdf, typst-render, typst-svg, typst-syntax and typst-html all at 0.15.1, along with the font parsing crates ttf-parser and skrifa and the Typst asset crates, one of which is pulled from a git tag.

The build profiles are the interesting engineering note. The release profile compiles at opt-level 3 with debug info off and symbols stripped, and there is a separate dist profile that inherits from it, turns on incremental compilation and uses thin link time optimisation, which is a deliberate trade for build speed on a large dependency graph.

A corpus, a fuzzing setup and a dev server

The package manifest shows how the project is tested, and the approach is unusual enough to be worth describing.

The dev script builds a Rust binary called typst-ts-dev-server and then runs it, and the run script starts it in http mode against a corpus directory, which is the fuzzers/corpora/ folder. The corpus script runs the same binary in compile mode over a named list of corpora, and the list is long: foundations, html, introspection, layout, loading, math, model, pdf, pdftags, playground, scripting, styling, symbols, syntax, text, visualize, lint, viewers and a set named after skyzh-cv.

Those names are the categories of Typst behaviour, and compiling a document from each of them is a way of checking that the compiler and the exporters still handle every feature area. It is a form of coverage that does not depend on a corpus of real documents, because the interesting cases in a typesetting system are the odd corners of the language, and those are what the corpora are for.

The fuzzers/ directory holds an incremental fuzzer, and the workspace contains tools/rkyv-assertions, which is a test crate for the serialization format the artefact uses. The typst crate family is developed by the Typst project, and the workspace credits both the Typst.ts developers and the Typst project developers as authors.

The JavaScript side is a yarn workspace with turbo driving the builds, and the workspace list shows how many surfaces there are, from the parser and compiler packages through the renderer to the React, Angular, Vue 3, Svelte and Solid component libraries, and there is a postinstall step that fixes a hoisted TypeScript link, which is the sort of detail that appears when a package tree has both Rust and TypeScript in it.

Apache-2.0, release candidates and a working container

The licence is Apache 2.0, with the text in the LICENSE file at the root and the workspace package metadata agreeing.

The version history is the part that tells you where the project is. The recent tags are v0.8.0-rc3 on 2026-06-29, v0.8.0-rc2 on 2026-06-23 and v0.8.0-rc1 on 2026-06-19, so the project is publishing release candidates of the 0.8 line and has been for a while. The workspace version string is the same 0.8.0-rc3, and the JavaScript root package is named reflexo-workspace at the same version.

A project that is still labelling itself with an rc suffix is telling you something about the interface surface, and for an adopter the practical reading is that the exported APIs may still move between releases. The repository is not archived and the last push was on 2026-10-08, so the work continues, and the release candidates are published as tags rather than hidden.

The Dockerfile is a two stage build with a rust 1.89.0 bullseye builder that installs git and compiles the CLI crate in release mode, and a debian 11 runtime image with the binary copied to /bin. The Docker image is therefore a command line tool image, not a server image, which fits with the CLI being the main Rust entry point.

The judgement for an adopter is that typst.ts is a substantial, well organised piece of work that solves a real problem, the browser rendering of Typst, and that its cost is a pre-1.0 API and a large WASM payload. The projects built on it, shiroa for books and the VS Code preview, are the best evidence of what it is for.

Editorial conclusion

Adopt typst.ts if you want Typst rendering in a browser or a JavaScript service, especially if you want the document to be rendered client side for interactivity or to be served from a static site without a Rust toolchain on the server. Do not adopt it if you only need a PDF or SVG on the server, since the native Typst toolchain already does that without a WASM payload, and treat the release candidate numbering as a signal that the API is still moving. Verify three things first: whether your platform is served, React or Angular, since the renderer and component libraries are separate packages, how fonts reach the client, because the all in one bundle downloads font assets from GitHub at runtime, and which artefact format you need, because the vector format carries features the plain SVG and canvas paths do not. The last push was on 2026-10-08 and the newest release is v0.8.0-rc3 from 2026-06-29.

Frequently asked questions

What is typst.ts?

A project to bring Typst to the JavaScript world. It provides a typst::World implementation and several exporters so a Typst document can be compiled and rendered in a browser, and it is licensed under Apache 2.0 with the JavaScript side published on npm.

What are the three rendering forms in typst.ts?

Form 1 renders to SVG on the server and embeds it statically in HTML, Form 2 preprocesses to a vector format artefact on the server and renders it in the browser, and Form 3 compiles the document in the browser and draws to a canvas element.

What is special about the vector format artefact?

It was developed specifically for Typst documents and holds compressed data for different theme and screen settings, with the bundle size optimised for Typst. It enables static but responsive rendering, incremental server side rendering through the compiler service, and serverless client side rendering.

How do I install the typst.ts CLI and the JavaScript packages?

The CLI is installed with cargo install --locked --git https://github.com/Myriad-Dreamin/typst.ts typst-ts-cli, or from a GitHub release, because the Rust crates are not on crates.io while the project has a git dependency on Typst. The JavaScript packages are on npm, with @myriaddreamin/typst.ts as the core wrapper and separate React and Angular libraries.

Does typst.ts work offline in the browser?

Not by default with the all-in-one bundle, because all-in-one.bundle.js downloads the font assets from GitHub in the browser and therefore needs an internet connection. The README points this out in the minimal example, and a deployment that must work offline has to serve the fonts itself.

How mature is typst.ts?

The recent tags are v0.8.0-rc3, v0.8.0-rc2 and v0.8.0-rc1, all published in June 2026, so the 0.8 line is still on release candidates. The last push was on 2026-10-08, the repository is not archived, and the workspace pins the Typst crates to 0.15.1.

Official sources

  1. License: Apache-2.0
  2. Myriad-Dreamin/typst.ts on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/myriad-dreamin-typst-ts.svg)](https://hysenlabs.com/projects/myriad-dreamin-typst-ts)

Was this useful?