Every figure below is a <script> or custom tag in the HTML source, typeset by MetaPost, pdfTeX, LuaTeX and dvisvgm. On this copy of the page the figures were saved in advance — mpost-wasm --prerender tags.html wrote them to figures/ — so they load as small static files, and the engines start only for the deliberately broken figure at the bottom. Typeset everything in this tab instead.
Every figure below is typeset on load by MetaPost, pdfTeX, LuaTeX and dvisvgm running in this tab, from a <script> or custom tag in the HTML source; the saved copies in figures/ and the browser's cache are being ignored. Load the saved figures instead.
A <script type="text/tikz"> holding just a tikzpicture. It is wrapped in a standalone document automatically; libraries come from data-libraries.
If the body contains \documentclass, it is compiled as is — any class, any package in the bundles, pgfplots included.
<tikz-diagram> and <metapost-diagram> work the same way and render when they enter the page (a MutationObserver catches later additions). Inside a custom element the content is HTML, so write < for <. A data-gdlibraries attribute (or any use of graph drawing or \directlua) switches that diagram to LuaTeX.
Every PGF/TikZ library is bundled, and so is spath3, whose knots and calligraphy libraries pgf does not ship: here decorations along a path, and a braid whose crossings the knots library finds and redraws.
<script type="text/metapost">: a body without beginfig becomes one figure; data-tex chooses the label engine.
With data-bundles="+opentype" on the loader, a diagram can use fontspec under data-engine="lualatex", or luaotfload directly in plain data-engine="luatex". data-fonts="woff2" embeds a subset of each face as a web font and writes real <text> instead of outlines: try selecting the words in the first figure. The bundle is opt-in because LaTeX under LuaTeX initialises luaotfload on every run once it can find it.
A broken diagram shows its diagnostics instead of failing silently.
<script type="module" src="https://your-host/mp-tikz-wasm/dist/auto.js" data-figures="figures/"></script>
<script type="text/tikz" data-libraries="arrows.meta">
\begin{tikzpicture} \draw[->] (0,0) -- (2,1); \end{tikzpicture}
</script>
<metapost-diagram>draw fullcircle scaled 50;</metapost-diagram>
Host the dist/ folder (the .wasm files, the JavaScript and bundles/) anywhere static; the script finds them relative to itself. Rendered SVGs are cached in IndexedDB by content hash, so a revisit shows the figures without running TeX. Add data-bundles="+opentype" for fontspec, data-worker="off" to run the engines on the page's own thread instead of a Web Worker, and data-log="debug" to watch the engines' output in the console (the menu above calls mpTikzWasm.setLogLevel(), which does the same at any time).
To spare first visits too, save the figures next to the page: npx mpost-wasm --prerender page.html writes figures/figure-HASH.svg for every diagram on the page (HASH is six characters of the hash of the element's source and attributes; add --opentype when the page uses fontspec), or open the page and call mpTikzWasm.saveFigures() — the button above — which writes the same files into a folder you pick (Chrome, Edge) or downloads them as a zip. With data-figures="figures/" on the loader, each element loads its file if it exists and the engines start only for the figures that are missing. The name is the content: a changed diagram gets a new file, and an old one is simply never requested.