{
    "archive_path": "archive/1791799470.531831",
    "base_url": "lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html",
    "basename": "type-safe-html-templating-in-zig.html",
    "bookmarked_date": "2026-10-12 10:04",
    "canonical": {
        "archive_org_path": "https://web.archive.org/web/lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html",
        "dom_path": "output.html",
        "favicon_path": "favicon.ico",
        "git_path": "git/",
        "google_favicon_path": "https://www.google.com/s2/favicons?domain=lalinsky.com",
        "headers_path": "headers.json",
        "htmltotext_path": "htmltotext.txt",
        "index_path": "index.html",
        "media_path": "media/",
        "mercury_path": "mercury/content.html",
        "pdf_path": "output.pdf",
        "readability_path": "readability/content.html",
        "screenshot_path": "screenshot.png",
        "singlefile_path": "singlefile.html",
        "warc_path": "warc/",
        "wget_path": "lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
    },
    "domain": "lalinsky.com",
    "extension": "html",
    "hash": "HCWPDNMD8H50RN563JK9",
    "history": {
        "archive_org": [],
        "dom": [],
        "favicon": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--output",
                    "favicon.ico",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://www.google.com/s2/favicons?domain=lalinsky.com"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-10-12T10:08:29.662627+00:00",
                "index_texts": null,
                "output": "favicon.ico",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T10:08:29.011544+00:00",
                "status": "succeeded"
            },
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--output",
                    "favicon.ico",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://www.google.com/s2/favicons?domain=lalinsky.com"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-10-12T16:30:58.269511+00:00",
                "index_texts": null,
                "output": "favicon.ico",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T16:30:57.493167+00:00",
                "status": "succeeded"
            }
        ],
        "git": [],
        "headers": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--head",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-10-12T10:08:30.025666+00:00",
                "index_texts": null,
                "output": "headers.json",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T10:08:29.671294+00:00",
                "status": "succeeded"
            },
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--head",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-10-12T16:30:58.696228+00:00",
                "index_texts": null,
                "output": "headers.json",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T16:30:58.276221+00:00",
                "status": "succeeded"
            }
        ],
        "htmltotext": [],
        "media": [],
        "mercury": [
            {
                "cmd": [
                    "/app/node_modules/@postlight/parser/cli.js",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "1.0.0",
                "end_ts": "2026-10-12T10:08:36.216901+00:00",
                "index_texts": null,
                "output": "mercury",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T10:08:32.615370+00:00",
                "status": "succeeded"
            },
            {
                "cmd": [
                    "/app/node_modules/@postlight/parser/cli.js",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "1.0.0",
                "end_ts": "2026-10-12T16:31:05.062026+00:00",
                "index_texts": null,
                "output": "mercury",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T16:31:01.155181+00:00",
                "status": "succeeded"
            }
        ],
        "pdf": [],
        "readability": [
            {
                "cmd": [
                    "/app/node_modules/readability-extractor/readability-extractor",
                    "/tmp/tmpiufm8te6",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "0.0.11",
                "end_ts": "2026-10-12T10:08:32.605888+00:00",
                "index_texts": [
                    "I\u2019ve done a lot of web development over the years. I started around the year 2000, just after PHP 3.0 was released and started taking over the web world. I\u2019ve used all kinds of approaches for generating HTML: raw PHP, string concatenation in Python, Smarty templates in PHP, Template Toolkit in Perl, and Jinja/Django templates in Python. Then, as the world moved on to SPAs and JavaScript frameworks, I stopped working on frontends.\n\nTwo years ago, I picked up Zig, and I\u2019d never have imagined I\u2019d be considering web development in such a low-level language. But as I was building my own ecosystem with zio and Dusty, I realized it\u2019s not that far-fetched. I built these libraries for API backends, where the output is JSON or MessagePack, but then I saw that with proper use of arena allocators, even web development is actually manageable, since you don\u2019t need to remember to deallocate all the strings that are typically involved. And with Zig\u2019s comptime, you can build very high-level interfaces without losing the performance benefits. And with the help of htmx or Datastar, you can even build SPAs without touching JavaScript/TypeScript, which I promised myself I\u2019d never do.\n\nThat said, one thing was still missing: templating. String concatenation was not an option, I didn\u2019t want to go back to the pre-2000 CGI days. I had a few requirements for a templating library:\n\n\n  It has to be type-safe, with all inputs typed and checked at compile time. I\u2019ve dealt with dynamic languages enough in my life, and I don\u2019t want to deal with runtime template errors anymore.\n  It has to be fast. No allocations, no intermediate state, just write the output to std.Io.Writer directly.\n  It needs to have safe defaults. I don\u2019t want to deal with XSS anymore, so all inputs have to be escaped by default.\n  It should still feel like writing HTML. I didn\u2019t want a Zig-based DSL I\u2019d have to fight constantly.\n\n\nI couldn\u2019t find any solution that would satisfy all these requirements. Then I saw Ziex and I was amazed. It never occurred to me that the JSX approach could be done outside of JavaScript. The developer experience Nurul Huda managed to build in Zig was just unimaginable to me. It didn\u2019t fit my needs directly, because I didn\u2019t want a WASM framework, but the syntax and his approach to integrating Zig code into templates gave me some ideas. Then, after further research, I discovered Templ for Go, and it was pretty obvious to me what I wanted to build.\n\nSo, let me present zt (I\u2019m not good at naming, sorry). It\u2019s an adaptation of Templ to Zig. The templates are parsed and transpiled to Zig code during zig build. That means you can import them directly from your app code, but also, perhaps even more importantly, the templates can import your app code. As a result, all parameters can be fully typed. If something can\u2019t be rendered, the Zig compiler will tell you so. The generated code is fairly simple, all it does is write to a std.Io.Writer. You can write directly to a socket or accumulate the output in a buffer, your choice. Here is what a template looks like:\n\nconst User = @import(\"../models.zig\").User;\n\npub templ Layout(title: []const u8) {\n    <!DOCTYPE html>\n    <html>\n        <head>\n            <title>{title}</title>\n        </head>\n        <body>\n            @children\n        </body>\n    </html>\n}\n\npub templ HomePage(user: ?User) {\n    @Layout(\"Home\") {\n        if (user) |u| {\n            <h1>Welcome back, {u.name}!</h1>\n            <a href=\"/users/{u.id}\">Your profile</a>\n        } else {\n            <h1>Welcome, guest!</h1>\n            <a href=\"/login\">Log in</a>\n        }\n    }\n}\n\n\nAnd here is how you would use it from Zig code:\n\nconst std = @import(\"std\");\nconst User = @import(\"models.zig\").User;\nconst pages = @import(\"templates/pages.zig\");\n\npub fn main(init: std.process.Init) !void {\n    var buf: [4096]u8 = undefined;\n    var stdout = std.Io.File.stdout().writer(init.io, &buf);\n    const w = &stdout.interface;\n\n    const user: User = .{ .id = 1, .name = \"Lukas\" };\n    try pages.HomePage.render(.{user}, w);\n    try w.flush();\n}\n\n\nIf you want to use it inside Dusty to render an HTML page, you just do this:\n\ntry res.render(.html, pages.HomePage, .{user});\n\n\nAs a side note, the main snippet above has a very non-obvious bug in error handling if you use the same pattern somewhere std.Io cancellation matters. I\u2019ll probably write a blog post about it, but if you are interested, check out this Ziggit thread. The render function in Dusty that wraps the std.Io.Writer handling solves it.\n\nAll dynamic values are HTML-escaped by default, both in text and in attributes, and values in URL attributes like href or src are also checked for dangerous schemes. If you really need to output raw HTML, you have to ask for it explicitly with {!value}, so it\u2019s easy to spot in the template. The parser also requires all elements to be properly closed, so you can\u2019t accidentally produce broken markup. It won\u2019t protect you from everything, but it removes the most common sources of XSS.\n\nWhat I like the most is that template errors are just Zig compiler errors. If you make a typo in the template above and write {u.nmae} instead of {u.name}, zig build will tell you:\n\nsrc/templates/pages.zig:45:43: error: no field named 'nmae' in struct 'models.User'\n            try zt.writeEscaped(writer, u.nmae); // pages.zt:18:31\n                                          ^~~~\nsrc/models.zig:1:18: note: struct declared here\npub const User = struct {\n                 ^~~~~~\n\n\nThe error points to the generated code, but each line has a comment with the location in the original template. The same applies to the calling side, if you try to pass a string where HomePage expects a ?User, it won\u2019t compile.\n\nBeyond the basics shown here, you can build reusable components and pass them around as values, and with @children you can build layouts that wrap other templates, which covers what you\u2019d use template inheritance for in other languages. Control flow is just Zig, so if, for and switch work as you\u2019d expect, including payload captures. All of it still compiles down to a sequence of writes, without any allocations.\n\nYou can have a look at the TODO example in Dusty. It\u2019s a simple htmx-based web app that showcases this library, plus other parts of Dusty that are needed for building a dynamic SPA.\n\nOne part of the syntax is still open. Block-level control flow is written as plain Zig, following the example of Templ, so a line starting with if, for or switch is parsed as code. That means text like \u201cif you forgot your password\u2026\u201d on its own line is a parse error, and you have to wrap it in an element or write it as a string expression. I\u2019m considering switching to @if, @for and @switch, similar to Razor or Twirl, which would remove the ambiguity, at the cost of slightly noisier templates. If you have an opinion on this, please leave a comment in this GitHub issue.\n\nAlthough multiple people are already using it, the project is not very mature yet, so I welcome any feedback. You can open a GitHub issue if you find any problems, or ping me on the Zig Discord."
                ],
                "output": "readability",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T10:08:30.890578+00:00",
                "status": "succeeded"
            },
            {
                "cmd": [
                    "/app/node_modules/readability-extractor/readability-extractor",
                    "/tmp/tmp9m8ug0jw",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "0.0.11",
                "end_ts": "2026-10-12T16:31:01.146618+00:00",
                "index_texts": [
                    "I\u2019ve done a lot of web development over the years. I started around the year 2000, just after PHP 3.0 was released and started taking over the web world. I\u2019ve used all kinds of approaches for generating HTML: raw PHP, string concatenation in Python, Smarty templates in PHP, Template Toolkit in Perl, and Jinja/Django templates in Python. Then, as the world moved on to SPAs and JavaScript frameworks, I stopped working on frontends.\n\nTwo years ago, I picked up Zig, and I\u2019d never have imagined I\u2019d be considering web development in such a low-level language. But as I was building my own ecosystem with zio and Dusty, I realized it\u2019s not that far-fetched. I built these libraries for API backends, where the output is JSON or MessagePack, but then I saw that with proper use of arena allocators, even web development is actually manageable, since you don\u2019t need to remember to deallocate all the strings that are typically involved. And with Zig\u2019s comptime, you can build very high-level interfaces without losing the performance benefits. And with the help of htmx or Datastar, you can even build SPAs without touching JavaScript/TypeScript, which I promised myself I\u2019d never do.\n\nThat said, one thing was still missing: templating. String concatenation was not an option, I didn\u2019t want to go back to the pre-2000 CGI days. I had a few requirements for a templating library:\n\n\n  It has to be type-safe, with all inputs typed and checked at compile time. I\u2019ve dealt with dynamic languages enough in my life, and I don\u2019t want to deal with runtime template errors anymore.\n  It has to be fast. No allocations, no intermediate state, just write the output to std.Io.Writer directly.\n  It needs to have safe defaults. I don\u2019t want to deal with XSS anymore, so all inputs have to be escaped by default.\n  It should still feel like writing HTML. I didn\u2019t want a Zig-based DSL I\u2019d have to fight constantly.\n\n\nI couldn\u2019t find any solution that would satisfy all these requirements. Then I saw Ziex and I was amazed. It never occurred to me that the JSX approach could be done outside of JavaScript. The developer experience Nurul Huda managed to build in Zig was just unimaginable to me. It didn\u2019t fit my needs directly, because I didn\u2019t want a WASM framework, but the syntax and his approach to integrating Zig code into templates gave me some ideas. Then, after further research, I discovered Templ for Go, and it was pretty obvious to me what I wanted to build.\n\nSo, let me present zt (I\u2019m not good at naming, sorry). It\u2019s an adaptation of Templ to Zig. The templates are parsed and transpiled to Zig code during zig build. That means you can import them directly from your app code, but also, perhaps even more importantly, the templates can import your app code. As a result, all parameters can be fully typed. If something can\u2019t be rendered, the Zig compiler will tell you so. The generated code is fairly simple, all it does is write to a std.Io.Writer. You can write directly to a socket or accumulate the output in a buffer, your choice. Here is what a template looks like:\n\nconst User = @import(\"../models.zig\").User;\n\npub templ Layout(title: []const u8) {\n    <!DOCTYPE html>\n    <html>\n        <head>\n            <title>{title}</title>\n        </head>\n        <body>\n            @children\n        </body>\n    </html>\n}\n\npub templ HomePage(user: ?User) {\n    @Layout(\"Home\") {\n        if (user) |u| {\n            <h1>Welcome back, {u.name}!</h1>\n            <a href=\"/users/{u.id}\">Your profile</a>\n        } else {\n            <h1>Welcome, guest!</h1>\n            <a href=\"/login\">Log in</a>\n        }\n    }\n}\n\n\nAnd here is how you would use it from Zig code:\n\nconst std = @import(\"std\");\nconst User = @import(\"models.zig\").User;\nconst pages = @import(\"templates/pages.zig\");\n\npub fn main(init: std.process.Init) !void {\n    var buf: [4096]u8 = undefined;\n    var stdout = std.Io.File.stdout().writer(init.io, &buf);\n    const w = &stdout.interface;\n\n    const user: User = .{ .id = 1, .name = \"Lukas\" };\n    try pages.HomePage.render(.{user}, w);\n    try w.flush();\n}\n\n\nIf you want to use it inside Dusty to render an HTML page, you just do this:\n\ntry res.render(.html, pages.HomePage, .{user});\n\n\nAs a side note, the main snippet above has a very non-obvious bug in error handling if you use the same pattern somewhere std.Io cancellation matters. I\u2019ll probably write a blog post about it, but if you are interested, check out this Ziggit thread. The render function in Dusty that wraps the std.Io.Writer handling solves it.\n\nAll dynamic values are HTML-escaped by default, both in text and in attributes, and values in URL attributes like href or src are also checked for dangerous schemes. If you really need to output raw HTML, you have to ask for it explicitly with {!value}, so it\u2019s easy to spot in the template. The parser also requires all elements to be properly closed, so you can\u2019t accidentally produce broken markup. It won\u2019t protect you from everything, but it removes the most common sources of XSS.\n\nWhat I like the most is that template errors are just Zig compiler errors. If you make a typo in the template above and write {u.nmae} instead of {u.name}, zig build will tell you:\n\nsrc/templates/pages.zig:45:43: error: no field named 'nmae' in struct 'models.User'\n            try zt.writeEscaped(writer, u.nmae); // pages.zt:18:31\n                                          ^~~~\nsrc/models.zig:1:18: note: struct declared here\npub const User = struct {\n                 ^~~~~~\n\n\nThe error points to the generated code, but each line has a comment with the location in the original template. The same applies to the calling side, if you try to pass a string where HomePage expects a ?User, it won\u2019t compile.\n\nBeyond the basics shown here, you can build reusable components and pass them around as values, and with @children you can build layouts that wrap other templates, which covers what you\u2019d use template inheritance for in other languages. Control flow is just Zig, so if, for and switch work as you\u2019d expect, including payload captures. All of it still compiles down to a sequence of writes, without any allocations.\n\nYou can have a look at the TODO example in Dusty. It\u2019s a simple htmx-based web app that showcases this library, plus other parts of Dusty that are needed for building a dynamic SPA.\n\nOne part of the syntax is still open. Block-level control flow is written as plain Zig, following the example of Templ, so a line starting with if, for or switch is parsed as code. That means text like \u201cif you forgot your password\u2026\u201d on its own line is a parse error, and you have to wrap it in an element or write it as a string expression. I\u2019m considering switching to @if, @for and @switch, similar to Razor or Twirl, which would remove the ambiguity, at the cost of slightly noisier templates. If you have an opinion on this, please leave a comment in this GitHub issue.\n\nAlthough multiple people are already using it, the project is not very mature yet, so I welcome any feedback. You can open a GitHub issue if you find any problems, or ping me on the Zig Discord."
                ],
                "output": "readability",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T16:30:59.058993+00:00",
                "status": "succeeded"
            }
        ],
        "screenshot": [],
        "singlefile": [],
        "title": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-10-12T10:08:30.883248+00:00",
                "index_texts": null,
                "output": "Type-safe HTML templating in Zig | Luk\u00e1\u0161 Lalinsk\u00fd",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T10:08:30.861098+00:00",
                "status": "succeeded"
            },
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-10-12T16:30:59.054269+00:00",
                "index_texts": null,
                "output": "Type-safe HTML templating in Zig | Luk\u00e1\u0161 Lalinsk\u00fd",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T16:30:59.037124+00:00",
                "status": "succeeded"
            }
        ],
        "wget": [
            {
                "cmd": [
                    "wget",
                    "--no-verbose",
                    "--adjust-extension",
                    "--convert-links",
                    "--force-directories",
                    "--span-hosts",
                    "--no-parent",
                    "-e",
                    "robots=off",
                    "--reject=js,mjs,woff,woff2,ttf,otf,eot,mp4,m4v,mov,webm,ogv,mkv,avi,flv",
                    "--timeout=120",
                    "--restrict-file-names=windows",
                    "--page-requisites",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) wget/GNU Wget 1.21.3",
                    "--compression=auto",
                    "--timestamping",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "GNU Wget 1.21.3",
                "end_ts": "2026-10-12T10:08:30.852590+00:00",
                "index_texts": null,
                "output": "lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T10:08:30.036773+00:00",
                "status": "succeeded"
            },
            {
                "cmd": [
                    "wget",
                    "--no-verbose",
                    "--adjust-extension",
                    "--convert-links",
                    "--force-directories",
                    "--span-hosts",
                    "--no-parent",
                    "-e",
                    "robots=off",
                    "--reject=js,mjs,woff,woff2,ttf,otf,eot,mp4,m4v,mov,webm,ogv,mkv,avi,flv",
                    "--timeout=120",
                    "--restrict-file-names=windows",
                    "--page-requisites",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) wget/GNU Wget 1.21.3",
                    "--compression=auto",
                    "--timestamping",
                    "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
                ],
                "cmd_version": "GNU Wget 1.21.3",
                "end_ts": "2026-10-12T16:30:59.031310+00:00",
                "index_texts": null,
                "output": "IndexError: list index out of range",
                "pwd": "/data/archive/1791799470.531831",
                "schema": "ArchiveResult",
                "start_ts": "2026-10-12T16:30:58.703023+00:00",
                "status": "failed"
            }
        ]
    },
    "icons": null,
    "is_archived": true,
    "is_static": false,
    "latest": {
        "archive_org": null,
        "dom": null,
        "favicon": "favicon.ico",
        "git": null,
        "media": null,
        "pdf": null,
        "screenshot": null,
        "singlefile": null,
        "title": "Type-safe HTML templating in Zig | Luk\u00e1\u0161 Lalinsk\u00fd",
        "warc": null,
        "wget": "IndexError: list index out of range"
    },
    "link_dir": "/data/archive/1791799470.531831",
    "newest_archive_date": "2026-10-12T16:31:01.155181+00:00",
    "num_failures": 1,
    "num_outputs": 11,
    "oldest_archive_date": "2026-10-12T10:08:29.011544+00:00",
    "path": "/2026/10/11/type-safe-html-templating-in-zig.html",
    "schema": "Link",
    "scheme": "https",
    "snapshot_id": "253e2a2a-acee-434b-952a-0e666b2f28f1",
    "sources": [
        "/data/sources/1791799470-import.txt"
    ],
    "tags": ",war-wiki",
    "tags_str": "war-wiki",
    "timestamp": "1791799470.531831",
    "title": "Type-safe HTML templating in Zig | Luk\u00e1\u0161 Lalinsk\u00fd",
    "updated": "2026-10-12T16:30:57.492953+00:00",
    "updated_date": "2026-10-12 16:30",
    "url": "https://lalinsky.com/2026/10/11/type-safe-html-templating-in-zig.html"
}