An open API service indexing awesome lists of open source software.

https://github.com/muhammad-fiaz/zix

A fast, modern web framework for Zig.
https://github.com/muhammad-fiaz/zix

web-application web-development web-server zig zig-lang zig-language zig-package zix zix-framework zix-library zix-web

Last synced: about 19 hours ago
JSON representation

A fast, modern web framework for Zig.

Awesome Lists containing this project

README

          

Documentation
Zig Version
GitHub stars
GitHub issues
GitHub pull requests
License
CI

A fast, modern web framework for Zig.

Documentation |
API Reference |
Quick Start |
Contributing

## Overview

Zix is a modern web framework for the Zig programming language. It provides a familiar, intuitive API for building web applications while leveraging Zig's performance, memory safety, and compile-time guarantees.

> [!NOTE]
> Zix is a work in progress and Docs are not yet ready but you can use `zig build docs` to generate docs.

**⭐️ If you love `zix`, make sure to give it a star! ⭐️**

## Quick Start

### Installation

Add Zix to your `build.zig.zon`:

```bash
zig fetch --save git+https://github.com/muhammad-fiaz/zix
```

Then in your `build.zig`:

```zig
const zix_dep = b.dependency("zix", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("zix", zix_dep.module("zix"));
```

### Hello World

```zig
const std = @import("std");
const zix = @import("zix");

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();

var app = try zix.createApp(allocator, .{
.port = 3000,
});
defer {
app.deinit();
allocator.destroy(app);
}

try app.get("/", struct {
fn handler(ctx: *zix.Context) !void {
try ctx.text("Hello, World!");
}
}.handler);

try app.get("/json", struct {
fn handler(ctx: *zix.Context) !void {
try ctx.json(.{ .message = "Hello!", .framework = "Zix" });
}
}.handler);

try app.run();
}
```

## Configuration

All configuration is centralized in a single `Config` struct:

```zig
var app = try zix.createApp(allocator, .{
.address = "0.0.0.0",
.port = 8080,
.enable_logging = true,
.enable_security_headers = true,
.cors_enabled = true,
.cors_allow_origin = "*",
.template_dir = "templates",
.static_dir = "public",
.static_mount_path = "/static",
.debug_mode = true,
});
```

## Routing

```zig
// HTTP methods
try app.get("/users", listUsers);
try app.post("/users", createUser);
try app.put("/users/:id", updateUser);
try app.patch("/users/:id", patchUser);
try app.delete("/users/:id", deleteUser);

// Route parameters
try app.get("/users/:id", struct {
fn handler(ctx: *zix.Context) !void {
const id = ctx.param("id") orelse "unknown";
try ctx.json(.{ .user_id = id });
}
}.handler);

// Query parameters
try app.get("/search", struct {
fn handler(ctx: *zix.Context) !void {
const query = try ctx.query("q") orelse "";
const page = try ctx.query("page") orelse "1";
try ctx.json(.{ .query = query, .page = page });
}
}.handler);
```

## Middleware

```zig
// Global middleware
try app.use(zix.middleware.securityHeaders());
try app.use(zix.middleware.cors());
try app.use(zix.middleware.recovery());

// Custom middleware
const authMiddleware = struct {
fn check(ctx: *zix.Context, next: zix.NextFn) !void {
const token = ctx.header("Authorization");
if (token == null) {
try ctx.unauthorized();
ctx.abort();
return;
}
try next(ctx);
}
}.check;

try app.use(authMiddleware);
```

## Response Types

```zig
// Text
try ctx.text("Hello, World!");

// HTML
try ctx.html("

Welcome

");

// JSON
try ctx.json(.{ .status = "ok", .count = 42 });

// Redirect
try ctx.redirect("/login");

// File download
try ctx.sendFile("report.pdf", "monthly-report.pdf");

// Status codes
_ = ctx.status(201);
try ctx.json(.{ .created = true });

// Cookies
try ctx.setCookie(.{
.name = "session",
.value = "abc123",
.max_age = 3600,
.http_only = true,
});
```

## External Logger

Plug in your own logging backend:

```zig
fn myLogger(level: zix.Level, message: []const u8, timestamp: i64) void {
// Send to your logging service
std.debug.print("[{s}] {s}\n", .{ level.toString(), message });
}

app.setExternalLogger(myLogger);
```

## Static Files

```zig
try app.static("/assets", "public");
```

Files in `public/` will be served at `/assets/`:
- `public/css/style.css` → `/assets/css/style.css`
- `public/js/app.js` → `/assets/js/app.js`

## Templates

```zig
app.enableTemplates();

try app.get("/", struct {
fn handler(ctx: *zix.Context) !void {
try ctx.render("index.html", .{
.title = "Welcome",
.user = "Alice",
});
}
}.handler);
```

Template syntax:
```html

{{ title }}


{% if user %}

Hello, {{ user }}!


{% endif %}
{% for item in items %}
  • {{ item }}

  • {% endfor %}
    ```

    ## Error Handling

    ```zig
    // Custom 404 handler
    app.notFound(struct {
    fn handler(ctx: *zix.Context) !void {
    _ = ctx.status(404);
    try ctx.json(.{ .error = "Resource not found" });
    }
    }.handler);

    // Custom error handler for specific errors
    try app.errorHandler("MyError", struct {
    fn handler(ctx: *zix.Context, err: anyerror) anyerror!void {
    _ = err;
    try ctx.status(500).json(.{ .error = "A custom error occurred" });
    }
    }.handler);
    ```

    ## Building and Running

    ```bash
    # Build the library
    zig build

    # Run tests
    zig build test

    # Build and run examples
    zig build example-basic
    zig build run-basic

    zig build example-json-api
    zig build run-json-api

    # Generate documentation
    zig build docs
    ```

    ## License

    This project is licensed under the Apache-2.0 License. See the [LICENSE](LICENSE) file for details.

    ## Contributing

    Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.