Why Weld
Weld is a small, statically-typed web-service language that compiles to Zig — and, through Zig, to a native static binary for the architecture of your choice.
hello.weld ──weld──▶ hello.zig ──zig build-exe──▶ native binary
(your source) (generated) (-target …) (x86_64 / aarch64 / riscv64 / …)Weld is itself written in Zig, so the whole toolchain is one dependency: the Zig compiler.
Why compile to Zig?
Zig ships a batteries-included, LLVM-free cross-compiler. By emitting Zig, Weld inherits:
- Cross-compilation for free —
-target aarch64-linux,riscv64-linux, … no extra toolchains. - Small, static binaries — the generated server links only
std. - A stable C ABI and a real optimizer — without Weld having to own a backend.
What you get
A .weld file becomes a running, cross-compiled native HTTP server — with path parameters, wildcards, typed records, enums, sum types, generics, and response interpolation — plus a generated TypeScript/JS client for the frontend. WebSocket hubs with connect-time auth and request-id-correlated method calls run on the same port.
The integrations are written from scratch in pure Zig, depending only on std:
- Native Postgres over the v3 wire protocol (no libpq), with prepared statements, connection pooling, SCRAM-SHA-256 auth, and transactions.
- HTTP / HTTPS upstreams with a real TLS handshake and CA verification.
- gRPC over a from-scratch HTTP/2 (h2c) + protobuf stack — unary and all three streaming modes.
- WebSocket hubs implementing the RFC 6455 handshake and frame codec by hand.
- JWT (HS256 verify/decode) and rate limiting written in Weld itself.
The example that started it
route GET "/" {
type "text/html"
respond "<h1>Weld API</h1>\n"
}
# :id is a typed int; {id} interpolates it (a bad int → 400)
route GET "/users/:id" (id: int) {
respond "user id = {id}\n"
}
# two typed params plus an optional query param, defaulted with ??
route GET "/users/:id/posts/:post" (id: int, post: int, query q: string?) {
respond "user {id}, post {post}, filter={q ?? "none"}\n"
}
# trailing wildcard captures the rest of the path
route GET "/files/*path" {
respond "serving file: {path}\n"
}$ curl localhost:8080/users/7/posts/99?q=recent
user 7, post 99, filter=recent
$ curl localhost:8080/files/docs/readme.md
serving file: docs/readme.mdStatus
Working MVP: a .weld file becomes a running, cross-compiled native HTTP server plus a generated client. Not production-ready.
Next: Getting Started.