Ziex

/

Full-stack web framework for Zig.

Compile-time safety, deterministic performance, absolute simplicity, and a delightful developer experience.

v0.1.0-dev.1259Zig 0.16.0
curl -fsSL https://ziex.dev/install | bash
zx init
powershell -c "irm ziex.dev/install.ps1 | iex"
zx init
npm init ziex
bun create ziex
git clone https://github.com/ziex-dev/template-starter my-app
cd my-app && zig build dev
Ziguana Mascot

Features

Everything you need to build fast, safe, and deployable web applications.

Fast Performance

Significantly faster at SSR than many other frameworks. Optimized for speed and low latency.

Familiar Syntax

Familiar plain HTML-style markup, with full access to Zig's control flow.

File System Routing

Just files in folders to create routes.

API Routes

Create API endpoints by adding route.zig files to your project.

Hybrid Rendering

Client-side rendering for interactive experiences when you need it.

Control Flow

if/else, for/while, and switch all work as expected. It's just Zig syntax.

Developer Tooling

CLI, hot reload, and editor extensions for the best development experience.

Deploy Anywhere

Standalone binaries, Cloudflare, Vercel, or any edge runtime host. Build once, run anywhere.

Predictable Memory

Explicit memory management of Zig, no hidden allocations.

Performance

View benchmark →
Each framework runs in a Docker container limited to 2 CPU cores and 2 GB RAM.

Ziex
35k
FrameworkZiex
Requests/sec35,732
P50 Latency0.67 ms
P99 Latency3.73 ms
8.8k
FrameworkLeptos
Requests/sec8,778
P50 Latency2.90 ms
P99 Latency9.51 ms
5.6k
FrameworkDioxus
Requests/sec5,622
P50 Latency1.56 ms
P99 Latency44.06 ms
2.4k
FrameworkJetzig
Requests/sec2,378
P50 Latency11.55 ms
P99 Latency36.22 ms
1.5k
FrameworkSolidStart
Requests/sec1,516
P50 Latency16.58 ms
P99 Latency70.29 ms
267
FrameworkNext.js
Requests/sec267
P50 Latency102.28 ms
P99 Latency282.14 ms
Dockerized SSR endpoint hit with 3000 requests at 30 concurrent connections, averaged over 3 runs.
Ziex
15.8%
FrameworkZiex
Avg CPU15.8%
Peak CPU32.8%
Requests/sec35,732
35.8%
FrameworkLeptos
Avg CPU35.8%
Peak CPU69.7%
Requests/sec8,778
41.0%
FrameworkDioxus
Avg CPU41.0%
Peak CPU74.8%
Requests/sec5,622
58.8%
FrameworkSolidStart
Avg CPU58.8%
Peak CPU84.1%
Requests/sec1,516
63.4%
FrameworkJetzig
Avg CPU63.4%
Peak CPU91.8%
Requests/sec2,378
68.8%
FrameworkNext.js
Avg CPU68.8%
Peak CPU89.4%
Requests/sec267
Average CPU utilization during the load test via cgroup cpu.stat. Hover for peak CPU.
Ziex
6.7 MB
FrameworkZiex
Idle Memory1.9 MB
Peak Memory6.7 MB
6.7 MB
FrameworkLeptos
Idle Memory1.7 MB
Peak Memory6.7 MB
6.7 MB
FrameworkDioxus
Idle Memory1.9 MB
Peak Memory6.7 MB
7.2 MB
FrameworkJetzig
Idle Memory3.5 MB
Peak Memory7.2 MB
136.2 MB
FrameworkSolidStart
Idle Memory31.0 MB
Peak Memory136.2 MB
252.1 MB
FrameworkNext.js
Idle Memory77.9 MB
Peak Memory252.1 MB
Peak container RSS during load test. Lower is better. Hover for idle memory.
243 ms
FrameworkLeptos
Cold Start243 ms
Image Size19 MB
260 ms
FrameworkDioxus
Cold Start260 ms
Image Size94 MB
Ziex
287 ms
FrameworkZiex
Cold Start287 ms
Image Size14 MB
299 ms
FrameworkJetzig
Cold Start299 ms
Image Size62 MB
478 ms
FrameworkSolidStart
Cold Start478 ms
Image Size351 MB
863 ms
FrameworkNext.js
Cold Start863 ms
Image Size275 MB
Time for the container to start and become ready to serve requests. Lower is better.
Ziex
14 MB
FrameworkZiex
Image Size14 MB
Binary Size6.2 MB
19 MB
FrameworkLeptos
Image Size19 MB
Binary Size10.9 MB
62 MB
FrameworkJetzig
Image Size62 MB
Binary Size54.4 MB
94 MB
FrameworkDioxus
Image Size94 MB
Binary Size9.5 MB
275 MB
FrameworkNext.js
Image Size275 MB
Binary SizeN/A
351 MB
FrameworkSolidStart
Image Size351 MB
Binary SizeN/A
Size of the final Docker image. Smaller images are faster to deploy and use less storage.
Last benchmarked on 2026-08-02View CI run →

Deploy Anywhere.

Ziex compiles to a single, statically linked binary or a WASI module, making it compatible with every major cloud provider and edge network.

Standalone

Deploy as a self-contained binary on Linux, macOS, Windows andy many more platforms that Zig supports.

Edge Anywhere

Deploy to the edge via WASI. Native bindings for Cloudflare and Vercel.

Static

Generate a statically pre-rendered site at build time. Deploy to GitHub Pages, Netlify, S3, or any CDN.

Cross-Platform

Build for any target from any host. Easily cross-compile optimized binaries for x86_64, aarch64, and more.

Code Examples

Short, focused snippets that show how each feature feels in practice.

Control Flow
const ControlIfProps = struct { is_admin: bool };
pub fn ControlIf(
    allocator: zx.Allocator,
    props: ControlIfProps,
) zx.Component {
    return (
        <div @{allocator}>
            {if (props.is_admin) (
                <span>Admin</span>
            ) else (
                <span>Member</span>
            )}
        </div>
    );
}
pub fn ControlIfOptional(allocator: zx.Allocator) zx.Component {
    const maybe_name: ?[]const u8 = "Zig";
    return (
        <div @{allocator}>
            {if (maybe_name) |name| (<span>{name}</span>)}
        </div>
    );
}
pub fn ControlIfError(allocator: zx.Allocator) zx.Component {
    const parsed =
        std.fmt.parseInt(u32, "42", 10);

    return (
        <div @{allocator}>
            {if (parsed) |value| (
                <span>{value}</span>
            ) else |err| (
                <span>{@errorName(err)}</span>
            )}
        </div>
    );
}
pub fn ControlWhile(allocator: zx.Allocator) zx.Component {
    var i: usize = 0;
    return (
        <ul @{allocator}>
            {while (i < 3) : (i += 1) (<li>Item {i + 1}</li>)}
        </ul>
    );
}
pub fn ControlWhileOptional(allocator: zx.Allocator) zx.Component {
    var maybe: ?u32 = 1;
    return (
        <ul @{allocator}>
            {while (maybe) |value| : (maybe = if (value < 3) value + 1 else null) (
                <li>{value}</li>
            )}
        </ul>
    );
}
pub fn ControlWhileError(allocator: zx.Allocator) zx.Component {
    var n: u32 = 1;
    return (
        <div @{allocator}>
            {while (parseOnce(&n)) |value| (
                <span>{value}<br /></span>
            ) else |err| (
                <span>{@errorName(err)}</span>
            )}
        </div>
    );
}

fn parseOnce(n: *u32) !u32 {
    if (n.* < 100) {
        n.* += 1;
        return n.*;
    }
    return error.Done;
}
Caching
pub fn CacheComponent(
    allocator: zx.Allocator,
) !zx.Component {
    return (<Slow @{allocator} @caching="10s" />);
}

fn Slow(allocator: zx.Allocator) !zx.Component {
    try std.Io
        .sleep(zx.io(), .fromSeconds(2), .awake);
    return (<div @{allocator}>Slow</div>);
}
pub fn Page(
    ctx: zx.PageContext,
) !zx.Component {
    try std.Io
        .sleep(zx.io(), .fromSeconds(2), .awake);
    return (
        <div @allocator={ctx.arena}>
            <h1>Expensive Page</h1>
            <p>I take too long to load.</p>
        </div>
    );
}

pub const options = zx.PageOptions{
    .caching = .{ .ttl = .fromSeconds(300) },
};
File System Routing
pub fn Page(
    ctx: zx.PageContext,
) zx.Component {
    return (
        <div @allocator={ctx.arena}>
            <h1>Home</h1>
        </div>
    );
}
pub fn Layout(
    ctx: zx.LayoutContext,
    children: zx.Component,
) zx.Component {
    return (
        <html @allocator={ctx.arena}>
            <body>
                {children}
            </body>
        </html>
    );
}
Components
const ButtonProps = struct { label: []const u8 };
pub fn Button(
    ctx: *zx.ComponentCtx(ButtonProps),
) zx.Component {
    return (
        <button @allocator={ctx.allocator}>
            Click {ctx.props.label}
        </button>
    );
}
pub fn Fragment(
    allocator: zx.Allocator,
) zx.Component {
    return (
        <fragment @{allocator}>
            <span>One</span>
            <>
                <p>Two</p><p>Three</p>
            </>
        </fragment>
    );
}
pub fn SpreadProps(
    allocator: zx.Allocator,
) zx.Component {
    const attrs =
        .{ .class = "btn", .id = "cta" };
    const class = "primary";
    return (
        <section @{allocator}>
            <button {..attrs}>Spreading</button>
            <button {class}>Shorthand</button>
        </section>
    );
}
pub fn DynamicAttr(
    allocator: zx.Allocator,
) zx.Component {
    const is_active = true;
    const class = if (is_active) "active" else "idle";
    const color = if (is_active) "green" else "red";
    return (
        <section @{allocator}>
            <button class={class}>Go</button>
            <button style=`color: {color};`>
                Template String
            </button>
        </section>
    );
}
Dynamic Path
pages/[id]/page.zx
pub fn Page(ctx: zx.PageContext) zx.Component {
    const id = ctx.request.params.get("id");
    return (
        <section @allocator={ctx.arena}>
            <h1>User {id}</h1>
        </section>
    );
}
API Route
route.zig
pub fn PUT(ctx: zx.RouteContext) !void {
    try ctx.response.json(.{ .status = "ok" }, .{});
}

pub fn POST(ctx: zx.RouteContext) !void {
    const Data = struct { id: u32 };
    const data =
        try ctx.request.json(Data, .{});

    try ctx.response.json(.{
        .id = if (data) |d| d.id else 0,
        .created = true,
    }, .{});
}
WebSocket
routes/ws/route.zig
pub fn GET(ctx: zx.RouteContext) !void {
    try ctx.socket.upgrade({});
}

pub fn Socket(ctx: zx.SocketContext) !void {
    try ctx.socket.write(
        try ctx.fmt("{s}", .{ctx.message}),
    );
}

pub fn SocketOpen(ctx: zx.SocketOpenContext) !void {
    try ctx.socket.write("Opened!");
}
Client-side Rendering
counter.zx
pub fn Page(ctx: zx.PageContext) !zx.Component {
    return (
        <main @allocator={ctx.arena}>
            <Counter @rendering={.client} />
        </main>
    );
}
pub fn Counter(ctx: *zx.ComponentCtx(void)) zx.Component {
    const count = ctx.state(i32, 0);
    return (
        <div @allocator={ctx.allocator} class="counter">
            <button onclick={ctx.bind(increment)}>
                Click Me: {count}
            </button>
        </div>
    );
}
fn increment(e: *zx.client.Event.Stateful) void {
    const count = e.state(i32);
    count.set(count.get() + 1);
}
Preview