const features = [_]Feature{ .{ .icon_fn = icons.Lightning, .title = "Fast Performance", .description = "Significantly faster at SSR than many other frameworks. Optimized for speed and low latency." }, // .{ .icon_fn = icons.Shield, .title = "Deterministic Safety", .description = "Built on Zig's safety features. Zero undefined behavior at runtime. Predictable and reliable." }, .{ .icon_fn = icons.Code, .title = "Familiar Syntax", .description = "Familiar plain HTML-style markup, with full access to Zig's control flow." }, // .{ .icon_fn = icons.Globe, .title = "Edge First", .description = "Native support for WASI and Edge runtimes. Deploy to Cloudflare Workers or Vercel Edge with zero config." }, // .{ .icon_fn = icons.Package, .title = "Zero Dependencies", .description = "Self-contained framework. No node_modules, no external runtimes. Just one small binary." }, .{ .icon_fn = icons.Folder, .title = "File System Routing", .description = "Just files in folders to create routes." }, .{ .icon_fn = icons.Server, .title = "API Routes", .description = "Create API endpoints by adding route.zig files to your project." }, .{ .icon_fn = icons.Monitor, .title = "Hybrid Rendering", .description = "Client-side rendering for interactive experiences when you need it." }, .{ .icon_fn = icons.Flow, .title = "Control Flow", .description = "if/else, for/while, and switch all work as expected. It's just Zig syntax." }, .{ .icon_fn = icons.Wrench, .title = "Developer Tooling", .description = "CLI, hot reload, and editor extensions for the best development experience." }, .{ .icon_fn = icons.Rocket, .title = "Deploy Anywhere", .description = "Standalone binaries, Cloudflare, Vercel, or any edge runtime host. Build once, run anywhere." }, .{ .icon_fn = icons.Layers, .title = "Predictable Memory", .description = "Explicit memory management of Zig, no hidden allocations." }, }; const deployments = [_]Deployment{ .{ .icon_fn = icons.Terminal, .title = "Standalone", .description = "Deploy as a self-contained binary on Linux, macOS, Windows andy many more platforms that Zig supports." }, .{ .icon_fn = icons.Globe, .title = "Edge Anywhere", .description = "Deploy to the edge via WASI. Native bindings for Cloudflare and Vercel." }, .{ .icon_fn = icons.Layers, .title = "Static", .description = "Generate a statically pre-rendered site at build time. Deploy to GitHub Pages, Netlify, S3, or any CDN." }, .{ .icon_fn = icons.Package, .title = "Cross-Platform", .description = "Build for any target from any host. Easily cross-compile optimized binaries for x86_64, aarch64, and more." }, }; const benchmark_cwv_rows = [_]BenchmarkRow{ .{ .label = "Ziex", .value = 98, .display = "98%", .url = "" }, .{ .label = "Next.js", .value = 44, .display = "44%", .url = "https://nextjs.org" }, .{ .label = "Nuxt", .value = 42, .display = "42%", .url = "https://nuxt.com" }, .{ .label = "Leptos", .value = 27, .display = "27%", .url = "https://leptos.dev" }, }; // Import benchmark data from auto-generated file const bench_data = @import("bench.zon"); const benchfig = @import("benchfig.zon"); const bench_run = bench_data.run; const bench_results = bench_data.results; const bench_len = @typeInfo(@TypeOf(bench_results)).@"struct".field_types.len; // Helper function to format large numbers (e.g., 25153 -> "25k") fn formatLargeNumber(n: f64) []const u8 { if (n >= 1000) { const k = n / 1000; if (k >= 10) { return std.fmt.comptimePrint("{d}k", .{@as(u32, @intFromFloat(k))}); } else { return std.fmt.comptimePrint("{d:.1}k", .{k}); } } return std.fmt.comptimePrint("{d}", .{@as(u32, @intFromFloat(n))}); } // Helper function to format memory with 1 decimal place (e.g., 9.8 MB) fn formatMemory(mb: f64) []const u8 { return std.fmt.comptimePrint("{d:.1} MB", .{mb}); } // Helper function to format requests per second with comma separator fn formatRequests(n: f64) []const u8 { const int_val = @as(u32, @intFromFloat(n)); if (int_val >= 10000) { const thousands = int_val / 1000; const remainder = int_val % 1000; return std.fmt.comptimePrint("{d},{d:0>3}", .{ thousands, remainder }); } if (int_val >= 1000) { const thousands = int_val / 1000; const remainder = int_val % 1000; return std.fmt.comptimePrint("{d},{d}", .{ thousands, remainder }); } return std.fmt.comptimePrint("{d}", .{int_val}); } // Helper function to format latency in milliseconds fn formatLatency(ms: f64) []const u8 { return std.fmt.comptimePrint("{d:.2} ms", .{ms}); } // Helper function to format build time in seconds fn formatBuildTime(s: f64) []const u8 { const int_s = @as(u32, @intFromFloat(s)); if (int_s >= 60) { const mins = int_s / 60; const secs = int_s % 60; return std.fmt.comptimePrint("{d}m {d}s", .{ mins, secs }); } return std.fmt.comptimePrint("{d}s", .{int_s}); } // Helper function to format image size (e.g., "18 MB", "1.0 GB") fn formatImageSize(mb: f64) []const u8 { if (mb >= 1000) { const gb = mb / 1000; return std.fmt.comptimePrint("{d:.1} GB", .{gb}); } return std.fmt.comptimePrint("{d} MB", .{@as(u32, @intFromFloat(mb))}); } // Helper function to format cold start time in milliseconds fn formatColdStart(ms: f64) []const u8 { return std.fmt.comptimePrint("{d} ms", .{@as(u32, @intFromFloat(ms))}); } // Helper function to format CPU peak percentage fn formatCpuPeak(pct: f64) []const u8 { return std.fmt.comptimePrint("{d:.1}%", .{pct}); } // Helper function to format binary size in MB fn formatBinarySize(mb: f64) []const u8 { if (mb == 0) return "N/A"; return std.fmt.comptimePrint("{d:.1} MB", .{mb}); } // Map framework id to its website URL fn getFrameworkUrl(comptime id: []const u8) []const u8 { if (std.mem.eql(u8, id, "jetzig")) return "https://jetzig.dev"; if (std.mem.eql(u8, id, "leptos")) return "https://leptos.dev"; if (std.mem.eql(u8, id, "solidjs")) return "https://start.solidjs.com"; if (std.mem.eql(u8, id, "dioxus")) return "https://dioxuslabs.com"; if (std.mem.eql(u8, id, "nextjs")) return "https://nextjs.org"; return ""; } fn sortRows(rows: []BenchmarkRow, comptime lower_is_better: bool) void { std.sort.insertion(BenchmarkRow, rows, {}, struct { fn lessThan(_: void, a: BenchmarkRow, b: BenchmarkRow) bool { return if (lower_is_better) a.value < b.value else a.value > b.value; } }.lessThan); } fn buildSsrRows() [bench_len]BenchmarkRow { @setEvalBranchQuota(10000); var rows: [bench_len]BenchmarkRow = undefined; const field_names = @typeInfo(@TypeOf(bench_results)).@"struct".field_names; inline for (field_names, 0..) |field_name, i| { const d = @field(bench_results, field_name); rows[i] = .{ .label = d.label, .value = d.requests_per_sec, .display = formatLargeNumber(d.requests_per_sec), .url = getFrameworkUrl(d.id), .tooltip_metrics = &[_]TooltipMetric{ .{ .label = "Framework", .value = d.label }, .{ .label = "Requests/sec", .value = formatRequests(d.requests_per_sec) }, .{ .label = "P50 Latency", .value = formatLatency(d.p50_latency_ms) }, .{ .label = "P99 Latency", .value = formatLatency(d.p99_latency_ms) }, }, }; } sortRows(&rows, false); return rows; } fn buildMemoryRows() [bench_len]BenchmarkRow { @setEvalBranchQuota(10000); var rows: [bench_len]BenchmarkRow = undefined; const field_names = @typeInfo(@TypeOf(bench_results)).@"struct".field_names; inline for (field_names, 0..) |field_name, i| { const d = @field(bench_results, field_name); rows[i] = .{ .label = d.label, .value = d.peak_memory_mb, .display = formatMemory(d.peak_memory_mb), .url = getFrameworkUrl(d.id), .tooltip_metrics = &[_]TooltipMetric{ .{ .label = "Framework", .value = d.label }, .{ .label = "Idle Memory", .value = formatMemory(d.idle_memory_mb) }, .{ .label = "Peak Memory", .value = formatMemory(d.peak_memory_mb) }, }, }; } sortRows(&rows, true); return rows; } fn buildBuildTimeRows() [bench_len]BenchmarkRow { @setEvalBranchQuota(10000); var rows: [bench_len]BenchmarkRow = undefined; const field_names = @typeInfo(@TypeOf(bench_results)).@"struct".field_names; inline for (field_names, 0..) |field_name, i| { const d = @field(bench_results, field_name); rows[i] = .{ .label = d.label, .value = d.build_time_s, .display = formatBuildTime(d.build_time_s), .url = getFrameworkUrl(d.id), .tooltip_metrics = &[_]TooltipMetric{ .{ .label = "Framework", .value = d.label }, .{ .label = "Build Time", .value = formatBuildTime(d.build_time_s) }, }, }; } sortRows(&rows, true); return rows; } fn buildColdStartRows() [bench_len]BenchmarkRow { @setEvalBranchQuota(10000); var rows: [bench_len]BenchmarkRow = undefined; const field_names = @typeInfo(@TypeOf(bench_results)).@"struct".field_names; inline for (field_names, 0..) |field_name, i| { const d = @field(bench_results, field_name); rows[i] = .{ .label = d.label, .value = d.cold_start_ms, .display = formatColdStart(d.cold_start_ms), .url = getFrameworkUrl(d.id), .tooltip_metrics = &[_]TooltipMetric{ .{ .label = "Framework", .value = d.label }, .{ .label = "Cold Start", .value = formatColdStart(d.cold_start_ms) }, .{ .label = "Image Size", .value = formatImageSize(d.image_mb) }, }, }; } sortRows(&rows, true); return rows; } fn buildImageSizeRows() [bench_len]BenchmarkRow { @setEvalBranchQuota(10000); var rows: [bench_len]BenchmarkRow = undefined; const field_names = @typeInfo(@TypeOf(bench_results)).@"struct".field_names; inline for (field_names, 0..) |field_name, i| { const d = @field(bench_results, field_name); rows[i] = .{ .label = d.label, .value = d.image_mb, .display = formatImageSize(d.image_mb), .url = getFrameworkUrl(d.id), .tooltip_metrics = &[_]TooltipMetric{ .{ .label = "Framework", .value = d.label }, .{ .label = "Image Size", .value = formatImageSize(d.image_mb) }, .{ .label = "Binary Size", .value = formatBinarySize(d.binary_mb) }, }, }; } sortRows(&rows, true); return rows; } fn buildCpuUsageRows() [bench_len]BenchmarkRow { @setEvalBranchQuota(10000); var rows: [bench_len]BenchmarkRow = undefined; const field_names = @typeInfo(@TypeOf(bench_results)).@"struct".field_names; inline for (field_names, 0..) |field_name, i| { const d = @field(bench_results, field_name); rows[i] = .{ .label = d.label, .value = d.cpu_avg_pct, .display = formatCpuPeak(d.cpu_avg_pct), .url = getFrameworkUrl(d.id), .tooltip_metrics = &[_]TooltipMetric{ .{ .label = "Framework", .value = d.label }, .{ .label = "Avg CPU", .value = formatCpuPeak(d.cpu_avg_pct) }, .{ .label = "Peak CPU", .value = formatCpuPeak(d.cpu_peak_pct) }, .{ .label = "Requests/sec", .value = formatRequests(d.requests_per_sec) }, }, }; } sortRows(&rows, true); return rows; } const benchmark_ssr_rows = buildSsrRows(); const benchmark_memory_rows = buildMemoryRows(); const benchmark_build_time_rows = buildBuildTimeRows(); const benchmark_cold_start_rows = buildColdStartRows(); const benchmark_image_size_rows = buildImageSizeRows(); const benchmark_cpu_usage_rows = buildCpuUsageRows(); const benchmark_tabs = [_]BenchmarkTab{ // .{ // .id = "bench-tab-cwv", // .label = "Core Web Vitals", // .metric = "% of real-world sites with good Core Web Vitals", // .footnote = "Full report. Benchmarked against Next.js and Leptos using real-world Core Web Vitals.", // .rows = benchmark_cwv_rows[0..], // .checked = true, // }, .{ .id = "bench-tab-ssr", .label = "SSR", .metric = "Requests per second (higher is better)", .footnote = std.fmt.comptimePrint( "Dockerized SSR endpoint hit with {d} requests at {d} concurrent connections, averaged over {d} runs.", .{ benchfig.requests, benchfig.concurrency, benchfig.runs, }, ), .rows = benchmark_ssr_rows[0..], .checked = true, }, .{ .id = "bench-tab-cpu", .label = "CPU", .metric = "Average CPU usage during load (lower is better)", .footnote = "Average CPU utilization during the load test via cgroup cpu.stat. Hover for peak CPU.", .rows = benchmark_cpu_usage_rows[0..], .checked = false, .lower_is_better = true, }, .{ .id = "bench-tab-memory", .label = "Memory", .metric = "Peak memory under load (lower is better)", .footnote = "Peak container RSS during load test. Lower is better. Hover for idle memory.", .rows = benchmark_memory_rows[0..], .checked = false, .lower_is_better = true, }, .{ .id = "bench-tab-cold-start", .label = "Cold Start", .metric = "Cold start time in milliseconds (lower is better)", .footnote = "Time for the container to start and become ready to serve requests. Lower is better.", .rows = benchmark_cold_start_rows[0..], .checked = false, .lower_is_better = true, }, .{ .id = "bench-tab-image-size", .label = "Size", .metric = "Docker image size (lower is better)", .footnote = "Size of the final Docker image. Smaller images are faster to deploy and use less storage.", .rows = benchmark_image_size_rows[0..], .checked = false, .lower_is_better = true, }, // TODO: currently it is hard to auto calc build time from inside docker build // .{ // .id = "bench-tab-build", // .label = "Build Time", // .metric = "Docker image build time in seconds (lower is better)", // .footnote = "Time to build each framework's Docker image from scratch on the host machine. Lower is better.", // .rows = benchmark_build_time_rows[0..], // .checked = false, // .lower_is_better = true, // }, }; pub fn Page(ctx: zx.PageContext) zx.Component { const allocator = ctx.arena; const current_year = blk: { const timestamp: i64 = @intCast(@divFloor(std.Io.Timestamp.now(zx.io(), .real).nanoseconds, std.time.ns_per_s)); const seconds_per_year = 365.25 * 24 * 60 * 60; const years_since_epoch = @as(i64, @intFromFloat(@as(f64, @floatFromInt(timestamp)) / seconds_per_year)); break :blk 1970 + years_since_epoch; }; // const overview_code = @embedFile("./examples/overview.zx"); const feature_examples = @embedFile("./examples/feature_examples.zx"); const control_tabs = [_]CodeTab{ .{ .id = "control-tab-if", .label = "If", .section = "Control Flow: if", .code = "", .checked = true }, .{ .id = "control-tab-if-opt", .label = "If Optional", .section = "Control Flow: if optional capture", .code = "", .checked = false }, .{ .id = "control-tab-if-err", .label = "If Error", .section = "Control Flow: if error capture", .code = "", .checked = false }, .{ .id = "control-tab-while", .label = "While", .section = "Control Flow: while", .code = "", .checked = false }, .{ .id = "control-tab-while-opt", .label = "While Optional", .section = "Control Flow: while optional capture", .code = "", .checked = false }, .{ .id = "control-tab-while-err", .label = "While Error", .section = "Control Flow: while error capture", .code = "", .checked = false }, }; const caching_tabs = [_]CodeTab{ .{ .id = "caching-tab-component", .label = "Component", .section = "Caching: component", .code = "", .checked = true }, .{ .id = "caching-tab-page", .label = "Page", .section = "Caching: page", .code = "", .checked = false }, }; const fs_tabs = [_]CodeTab{ .{ .id = "fs-tab-page", .label = "Page", .section = "File System Routing: page", .code = "", .checked = true }, .{ .id = "fs-tab-layout", .label = "Layout", .section = "File System Routing: layout", .code = "", .checked = false }, }; const component_tabs = [_]CodeTab{ .{ .id = "component-tab-basics", .label = "Basics", .section = "Component: basics", .code = "", .checked = true }, .{ .id = "component-tab-frag", .label = "Fragment", .section = "Component: fragment", .code = "", .checked = false }, .{ .id = "component-tab-props", .label = "Props", .section = "Component: props", .code = "", .checked = false }, .{ .id = "component-tab-attr", .label = "Attributes", .section = "Component: attr", .code = "", .checked = false }, }; return (

Ziex

/

The full-stack web framework for Zig.

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

//
Ziguana Mascot

Features

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

{for (features) |f| ()}
View benchmark →
Each framework runs in a Docker container limited to 2 CPU cores and 2 GB RAM.` tabs={benchmark_tabs[0..]} run_url={bench_run.url} run_date={bench_run.date} /> // // //

Code Examples

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

)} /> )} /> )} /> )} /> )} /> )} /> )} /> )} />)} />
//
//
//
//

Familiar Syntax

//

// Familiar JSX like syntax or just like HTML with having access to Zig's control flow. //

//
// //
//
); } const Deployment = struct { icon_fn: *const fn (zx.Allocator) zx.Component, title: []const u8, description: []const u8 }; const Feature = struct { icon_fn: *const fn (zx.Allocator) zx.Component, title: []const u8, description: []const u8 }; fn FeatureCard(allocator: zx.Allocator, props: Feature) zx.Component { const IconComponent = props.icon_fn(allocator); return (
{IconComponent}

{props.title}

{props.description}

); } const TooltipMetric = struct { label: []const u8, value: []const u8, }; const BenchmarkRow = struct { label: []const u8, value: f64, display: []const u8, url: []const u8, tooltip_metrics: []const TooltipMetric = &[_]TooltipMetric{}, }; const BenchmarkRowViewProps = struct { row: BenchmarkRow, normalized_value: f64, }; const BenchmarkTab = struct { id: []const u8, label: []const u8, metric: []const u8, footnote: []const u8, rows: []const BenchmarkRow, checked: bool, lower_is_better: bool = false, }; const BenchmarksSectionProps = struct { eyebrow: []const u8, title: []const u8, subtitle: []const u8, tabs: []const BenchmarkTab, run_url: []const u8 = "", run_date: []const u8 = "", }; fn buildBenchTabStyles(allocator: zx.Allocator, container_id: []const u8, tabs: []const BenchmarkTab) []const u8 { var out = std.array_list.Managed(u8).init(allocator); defer out.deinit(); for (tabs) |tab| { out.appendSlice("#") catch unreachable; out.appendSlice(container_id) catch unreachable; out.appendSlice(":has(#") catch unreachable; out.appendSlice(tab.id) catch unreachable; out.appendSlice(":checked) .benchmarks-panel[data-tab=\"") catch unreachable; out.appendSlice(tab.id) catch unreachable; out.appendSlice("\"] { display: block; }\n") catch unreachable; out.appendSlice("#") catch unreachable; out.appendSlice(container_id) catch unreachable; out.appendSlice(":has(#") catch unreachable; out.appendSlice(tab.id) catch unreachable; out.appendSlice(":checked) label[for=\"") catch unreachable; out.appendSlice(tab.id) catch unreachable; out.appendSlice("\"] { color: #0c0f14; background: #4ade80; border-color: transparent; box-shadow: 0 8px 20px rgba(74, 222, 128, 0.25); }\n") catch unreachable; } return allocator.dupe(u8, out.items) catch unreachable; } fn BenchmarkRowView(allocator: zx.Allocator, props: BenchmarkRowViewProps) zx.Component { const style_value = std.fmt.allocPrint(allocator, "--value: {d:.3};", .{props.normalized_value}) catch unreachable; return (
{if (props.row.url.len > 0) ( {props.row.label} ) else ( {props.row.label} )}
{props.row.display}
{for (props.row.tooltip_metrics) |metric| (
{metric.label} {metric.value}
)}
); } fn normalizeValue(value: f64, rows: []const BenchmarkRow) f64 { if (rows.len == 0) return 0; var max_value = rows[0].value; for (rows[1..]) |row| { if (row.value > max_value) max_value = row.value; } if (max_value == 0) return 0; return value / max_value; } fn BenchmarksPanel(allocator: zx.Allocator, tab: BenchmarkTab) zx.Component { const panel_id = std.fmt.allocPrint(allocator, "panel-{s}", .{tab.id}) catch unreachable; const tab_id = std.fmt.allocPrint(allocator, "tab-{s}", .{tab.id}) catch unreachable; return (
//
{tab.metric}
{for (tab.rows) |row| ( )}
{tab.footnote}
); } fn BenchmarksSection(allocator: zx.Allocator, props: BenchmarksSectionProps) zx.Component { const tab_styles = buildBenchTabStyles(allocator, "benchmarks-tabs", props.tabs); return (
{props.eyebrow}

{props.title}

{props.subtitle}

{for (props.tabs) |tab| ( <> {if (tab.checked) ( ) else ( )} )}
{for (props.tabs) |tab| (BenchmarksPanel(allocator, tab))}
{if (props.run_url.len > 0) (
Last benchmarked on {props.run_date} View CI run →
)}
); } const DeploymentSectionProps = struct { allocator: zx.Allocator, }; fn DeploymentSection(allocator: zx.Allocator, _: DeploymentSectionProps) zx.Component { return (

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.

{for (deployments) |d| (
{d.icon_fn(allocator)}

{d.title}

{d.description}

)}
); } fn ArchitectureSection(allocator: zx.Allocator, _: struct {}) zx.Component { return (

Zero Overhead Pipeline

A request in Ziex travels through a streamlined pipeline written in native Zig code, bypassing the heavy overhead of interpreted runtimes.

{icons.Monitor(allocator)}
Browser
{icons.Server(allocator)}
Ziex Edge
{icons.Flow(allocator)}
Zig Router
{icons.Lightning(allocator)}
Handler
{icons.Layers(allocator)}
Response
); } fn TechnicalSection(allocator: zx.Allocator, _: struct {}) zx.Component { return (
Reliability

Statically Checked Components

Every tag, attribute, and component link is verified at compile-time. There are no runtime string-matching errors or missing props in production.

Efficiency

Deterministic Allocation

Ziex uses arena allocators for every request. Memory is allocated once and cleared instantly when the request ends. Zero garbage collection, zero memory leaks.

Resilience

WASI Isolation

Deploy your application inside a WASI sandbox. Hardware-level isolation ensures your app is secure and portable across any edge infrastructure.

Speed

Native Binary Size

A typical Ziex application is less than 5MB. No node_modules, no shared libraries. Just a high-performance binary ready to serve.

); } fn TestingSection(allocator: zx.Allocator, _: struct {}) zx.Component { return (

Deterministic Simulation Testing

Ziex components are tested using deterministic simulation. We simulate thousands of edge cases, network failures, and race conditions in milliseconds.

Local Time Real World
Simulated Time 10,000x Speed
); } const FeatureExampleProps = struct { title: []const u8, child: zx.Component, wide: bool, }; fn FeatureExample(allocator: zx.Allocator, props: FeatureExampleProps) zx.Component { const class_name = if (props.wide) "feature-example feature-example--wide" else "feature-example"; return (
{props.title}
{props.child}
); } const CodeWindowProps = struct { title: []const u8, code: []const u8, section: []const u8, source: []const u8, }; const CodeTab = struct { id: []const u8, label: []const u8, section: []const u8, code: []const u8, checked: bool, }; fn resolveCode(allocator: zx.Allocator, source: []const u8, section: []const u8, fallback: []const u8) []const u8 { const raw = if (section.len > 0 and source.len > 0) util.extractSection(allocator, source, section) else fallback; return util.highlightZx(allocator, raw) catch raw; } fn CodeWindow(allocator: zx.Allocator, props: CodeWindowProps) zx.Component { const highlighted = resolveCode(allocator, props.source, props.section, props.code); return (
{props.title}
{highlighted}
); } const CodeWindowTabsProps = struct { id: []const u8, name: []const u8, title: []const u8, tabs: []const CodeTab, video_url: []const u8, source: []const u8, }; const CodePreviewExampleProps = struct { title: []const u8, section: []const u8, source: []const u8, code: []const u8, preview: zx.Component, }; fn CodePreviewExample(allocator: zx.Allocator, props: CodePreviewExampleProps) zx.Component { const highlighted = resolveCode(allocator, props.source, props.section, props.code); return (
//
// //
{props.title}
{highlighted}
Preview
{props.preview}
); } fn buildTabStyles(allocator: zx.Allocator, container_id: []const u8, tabs: []const CodeTab) []const u8 { var out = std.array_list.Managed(u8).init(allocator); defer out.deinit(); for (tabs) |tab| { out.appendSlice("#") catch unreachable; out.appendSlice(container_id) catch unreachable; out.appendSlice(":has(#") catch unreachable; out.appendSlice(tab.id) catch unreachable; out.appendSlice(":checked) .code-example-panel[data-tab=\"") catch unreachable; out.appendSlice(tab.id) catch unreachable; out.appendSlice("\"] { display: block; }\n") catch unreachable; } return allocator.dupe(u8, out.items) catch unreachable; } fn CodeWindowTabs(allocator: zx.Allocator, props: CodeWindowTabsProps) zx.Component { const tab_styles = buildTabStyles(allocator, props.id, props.tabs); return (
{for (props.tabs) |tab| ( <> {if (tab.checked) ( ) else ( )} )}
{if (props.video_url.len > 0) ( )}
{if (props.title.len > 0) (
{props.title}
)}
{for (props.tabs) |tab| (renderTabPanel(allocator, props.source, tab))}
); } fn renderTabPanel(allocator: zx.Allocator, source: []const u8, tab: CodeTab) zx.Component { const highlighted = resolveCode(allocator, source, tab.section, tab.code); return (
{highlighted}
); } const std = @import("std"); const zx = @import("zx"); const util = @import("./reference/util.zig"); const icons = @import("./components/icons.zx"); const GitHubIcon = icons.GitHub; const DiscordIcon = icons.Discord; const InstallCLI = @import("./components/install_guide.zx").InstallCLI; const Version = @import("./components/version.zx").Version; const Examples = @import("./examples/feature_examples.zx"); const root = @import("root");