Zig HTML templating with no dependencies.
- HTML5-compatible - Standard HTML5 element support
- Accessible - First-class ARIA support via
.ariaproperty - HTMX-compatible - Built-in
.hxproperty for HTMX attributes - Type-safe - Strong typing for props (boolean, numeric, string)
- Secure - Automatic HTML escaping to prevent XSS
- Fast - ~2,200ns average render time (~450K templates/sec)
- Zero dependencies - Pure Zig, no external dependencies
const std = @import("std");
const ztl = @import("ztl");
pub fn main() !void {
const alloc = std.testing.allocator;
var z = ztl.Builder.init(alloc);
defer z.deinit();
const page = try z.html(.{
.props = .{ .lang = "en" },
.children = &[_]ztl.Element{
try z.head(.{}),
try z.body(.{
.children = &[_]ztl.Element{
try z.h1(.{ .content = .{ .text = "Hello, ztl!" } }),
try z.p(.{ .content = .{ .text = "Fast, safe HTML templating in Zig." } }),
},
}),
},
});
var buf = std.ArrayList(u8).init(alloc);
defer buf.deinit();
try page.render(&buf, alloc, false);
const html = try buf.toOwnedSlice(alloc);
defer alloc.free(html);
std.debug.print("{s}\n", .{html});
}Add ztl to your build.zig.zon:
.dependencies = .{
.ztl = .{
.url = "https://github.com/yourusername/ztl/archive/refs/tags/v0.1.0.tar.gz",
.hash = "...",
},
},Then in your build.zig:
const ztl = b.dependency("ztl", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("ztl", ztl.module("ztl"));- API Patterns - Choosing between
ztl.zigandztlc.zig - Usage Guide - Basic API, text content, typing, helpers, memory
- HTMX Support - Dynamic content loading and interactions
- ARIA Support - Accessibility features and patterns
- Streaming - Large template streaming with Writer API
- Examples - Complete usage examples
- Benchmarks - Performance characteristics and testing
Contributions are welcome! Please open an issue or PR.
MIT