Run and explore Zig in your browser, with compiler and LSP support built in.
Site: https://play.ziglang.cc/
| Path | Meaning |
|---|---|
/ |
Configurable default (versions.json → default, currently 0.16.0) |
/0.16.0/ |
Current stable pin (same binaries as /) |
/0.15.2/ |
Older pin (binaries from Release; rebuild only when forced/missing) |
Shared UI under /assets/. Per-version compilers:
/compilers/<id>/zig.<hash>.wasm
/compilers/<id>/zls.<hash>.wasm
/compilers/<id>/libcompiler_rt.<hash>.a
/compilers/<id>/zig.<hash>.tar.gz
/compilers/<id>/meta.json
Compiler asset filenames carry a content hash so the CDN can cache
them immutably; meta.json maps logical names → hashed filenames (the one
fixed-name file). Large binaries are never committed.
Design: docs/superpowers/specs/2026-07-26-multi-version-compilers-design.md
This site also ships a small ESM loader — https://play.ziglang.cc/zp-loader.js —
so other projects can fetch these compilers without re-implementing the
hash-filename / meta.json / Cache-Storage logic. Import it directly (works in
Web Workers):
import {
fetchCompilerFile,
compileCompilerWasm,
getZigLibDir,
listVersions,
} from "https://play.ziglang.cc/zp-loader.js";Always pass logical names — the loader resolves the content-hash filename
from each version's meta.json:
| Logical name | What |
|---|---|
zig.wasm |
the compiler |
zls.wasm |
the language server |
libcompiler_rt.a |
compiler-rt archive |
zig.tar.gz |
the standard-library tree |
// 1) List the published versions (cache: no-store).
const { default: def, versions } = await listVersions();
// → { default: "0.16.0", versions: [{id:"0.16.0",label:"0.16.0"}, …] }
// 2) Compile zig.wasm + load the std-lib tree for a version.
const zigModule = await compileCompilerWasm("0.16.0", "zig.wasm");
const stdLibDir = await getZigLibDir("0.16.0"); // WASI Directory from zig.tar.gz
// 3) Fetch any logical file as bytes (e.g. compiler-rt).
const crt = await fetchCompilerFile("0.16.0", "libcompiler_rt.a");Notes:
- Cross-origin fetch is permitted (the host serves permissive CORS). Large assets are cached by the loader via Cache Storage keyed by the hashed URL, so a hit is always the right bytes — offline-friendly after first load.
meta.jsonis always revalidated (cache: "no-store"), so new builds are visible without a cache-bust.- Self-hosting: call
configure({ origin: "https://your.host" })once before any other call to point at your own/compilers/<id>/…tree. The default origin is the loader's own host (https://play.ziglang.cc).
versions.json is the build orchestrator, not only the UI list:
| Field | Role |
|---|---|
default |
/ resolves to this id |
versions[].id / label |
URL path + dropdown |
versions[].zig.path / zig.git |
Source for that id (local path preferred; else clone git.ref) |
versions[].zig.patch |
Optional repo-relative patch applied after clone (CI) |
versions[].zls.url / hash |
Paired ZLS package |
versions[].zigVersionString |
Passed as -Dzig-version-string |
Source trees (do not use GitHub ziglang/zig master — it is a Codeberg stub):
| id | build | git | hostZig | notes |
|---|---|---|---|---|
0.16.0 |
in-tree |
codeberg.org/ziglang/zig@0.16.0 |
0.16.0 |
zig.wasm in-tree + ZLS 0.16.0 (Zig is not a package from 0.16) |
0.15.2 |
playground |
github.com/ziglang/zig@0.15.2 |
0.15.2 |
full zig+zls via repo build.zig |
Local overrides: ../zig-0.16.0, ../zig-wasm (0.15.2). Hosts via zvm i 0.16.0.
(A master tracking build existed until 2026-08; re-enable by restoring the
versions.json entry — the toolchain in scripts/ still supports
schedule/hostZig: master in-tree builds.)
npm run compilers:plan # dry-run: who would build
npm run compilers:stable # all pinned versions
npm run compilers -- --only 0.16.0Requires host Zig matching each pin (0.16.0 for the default; 0.15.2 if building that pin). Install with zvm i 0.16.0.
npm run compilers:stable # reads versions.json → zig build → public/compilers/<id>
npm install
npm run devOpen / (→ 0.16.0) or /0.16.0/ / /0.15.2/. Toolbar dropdown does full-page navigation.
npm run compilers:stable # or :scheduled / --select all
npm run build # vite + assemble-dist
npm run previewLive deploys run on the gx VPS webhook (branch master): a push to master
fires the GitHub webhook → the shared receiver on gx (adnanh/webhook) →
scripts/server/deploy.sh (fetch → compilers from the compilers Release →
npm ci + vite build → rsync to the web root, publish in ~1 min). Setup and
operations: scripts/server/README.md.
| Workflow | Role |
|---|---|
Build Compilers (build-compilers.yml) |
Manual workflow (workflow_dispatch). Compiles selected or all Zig / ZLS WebAssembly compiler targets from source and creates/updates the compilers Release on this repository. |
Deploy to GitHub Pages (deploy.yml) |
Dormant: it triggers on main only (live deploys come from master via the gx webhook) and GitHub Pages is not enabled. If adopted later, it reuses the compilers Release the same way the gx deploy does. |
Workflow strategy: Build compilers once → publish to GitHub Release → Pages deployment reuses release binaries.
Optional repository variables:
COMPILERS_RELEASE: Release tag containing compiler archives (defaults tocompilers).VITE_BASE: Base path for Vite assets (automatically configured byactions/configure-pages, e.g./play/).
Enjoy!