| ▲ | Nixtml: Static website and blog generator written in Nix(github.com) |
| 73 points by todsacerdoti 7 hours ago | 33 comments |
| |
|
| ▲ | mikepurvis 6 hours ago | parent | next [-] |
| As a nix person, I like this a lot and could see myself using it. My only criticism would be I don't love this kind of thing: "<!DOCTYPE html>\n"
+
html
[ (attrs.lang metadata.lang) ]
[
(head [ ] [ (partials.head context) ])
(body
[
(attrs.classes [
"font-sans"
"bg-white"
])
I understand that this is very flexible and powerful, but it immediately makes the templates highly non-portable and requiring of hand-authorship— fine for a personal blog by a code nerd, but a non-starter for when a designer is involved who will want to use visual tools. I see that right below that there's also a "normal string templating" option that's closer to conventional jinja2 or the like, but it's ultimately still pretty nix-ified.It might be worth some ifd [1] to allow a step that pre-processes conventional html + tags template files into the form that can be consumed by nixtml. [1]: or the still-experimental dynamic derivations: https://fzakaria.com/2025/03/10/an-early-look-at-nix-dynamic... |
| |
| ▲ | granra 5 hours ago | parent [-] | | I'm the author of nixtml. It's already doing IFD by using python to parse markdown content + metadata and superhtml to format the final HTML (a bit unnecessary, but I liked it while developing it). I really wanted the templates to just be nix functions. It shouldn't be an issue to pass the context to an external program with `pkgs.runCommand` or something and then read the result (IFD like you mentioned). Edit: I'm glad to hear you like it :) | | |
| ▲ | mikepurvis 4 hours ago | parent | next [-] | | Yeah, it feels like the more conventional way would be doing the template-filling as a build step, so it's Nix just for the overall structure managing a fixed build graph, and then a per-page Python run to actually fill templates and generate the snippets/pages. However, if you did want it to be nix all the way down and get more of that juicy dependency granularity, it could be more of a model where content and templates are transformed upfront into Nix source, which is then transformed and combined during evaluation. Obviously this is fairly slow in an IFD world where all that pre-work has to be serialized, but it would be interesting to experiment with what it looks like in a dynamic derivations context. | | |
| ▲ | granra 3 hours ago | parent [-] | | Yeah it would probably be more efficient to do the templating as a build step in the derivation that parses the markdown. But after making nixidy[1] I wanted to have a crack at making a static site generator _in nix_. I'm open to expanding it though of course :) [1]: https://github.com/arnarg/nixidy | | |
| ▲ | mikepurvis 3 hours ago | parent [-] | | Oh I can totally understand the impulse on that score. I guess going the way you have at the very least gets you out of some of the annoying handoffs of data between the two worlds, for example putting nix attrsets through toJSON so that they can be picked up on the Python side as template-fill variables. The ROS 1 world was full of this kind of thing for getting values between Python and CMake and it's truly gross, eg: https://github.com/ros/catkin/blob/noetic-devel/cmake/templa... | | |
| ▲ | granra 2 hours ago | parent [-] | | Out of curiousity, having never worked in the business of making websites, what would be accessible to a designer? Jinja2? | | |
| ▲ | mikepurvis 11 minutes ago | parent [-] | | I haven't for many years [1], but I think the current state of the art is stuff like webflow, silex, pinegrow. None of them _really_ let you directly open, say, django's template files and hack on them though, so there's still a gap where you've got a designer periodically exporting from a visual tool and then their changes having to be ported into the template representation. Obviously it's easy if all they touched was the CSS, but less obvious if markup is involved. Honestly seems like there's a bit of a gap here. Would be an interesting case for copilot tbh— here, take the old export and the new export, and make me a PR applying those changes to the templates in this repo. [1]: I was briefly an intern at a web shop in the late 00s and it was one guy doing Dreamweaver and the rest of us coding PHP around the assets it produced. |
|
|
|
| |
| ▲ | lloeki 4 hours ago | parent | prev [-] | | > I really wanted the templates to just be nix functions This feels like Ruby template engines like haml† and slim†† a lot, or the various xml builders††† too † https://github.com/haml/haml †† https://slim-template.github.io ††† https://nokogiri.org/rdoc/Nokogiri/XML/Builder.html#class-No... | | |
|
|
|
| ▲ | Y_Y 6 hours ago | parent | prev | next [-] |
| Cool. After using Nix for a while I got pretty fed up with the (subjective) unintuitiveness of the language†. It wasn't even that I thought it was a bad language, I just couldn't het it to click (and doubly so after the advent of flakes). All the same it seems to me like if you grok it it's a great fit for constructing recipes for building things reliably that are part of huge dependency trees, and so it's natural that it would be a good website generator too. † Luckily others shared this issue, and the result was Guix which solves that problem while introducing its own. |
| |
| ▲ | lillecarl 6 hours ago | parent [-] | | It's a pretty special language, lazy evaluation and very basic types. However after spending the time to learn it to an intermediate level I think it's pretty great. Flakes are not great however, they're what happens when you "overdo it", sadly the momentum is behind flakes because some UX/DX improvements came along with them (lockfile in repo). I think the stdenv being built on bash is worse than Nix language. Module system errors can be very hard to troubleshoot because of lazy eval, sadly I can't see a reasonable solution without worse tradeoffs :( | | |
| ▲ | Hnus 5 hours ago | parent [-] | | The flakes were the main UX/DX improvement for me. Before them I honestly could not do anything. The learning curve was so incredibly steep it almost felt like the people behind Nix were being malicious or intentionally gatekeeping. You finally stumble onto something you can at least partly understand, but then the powers that be throw two last obstacles at you like, First, flakes are "experimental", so you have to enable them. Back then there were like three slightly different CLI commands to do it, and it felt like none worked from like 5 tutorial tabs I had open, putting it `experimental-features =` into flake you are trying to switch to does not work obviously. Then you hit the classic situation where your flake is not committed or staged, so Nix refuses to see it. And instead of telling you that, it prints this abomination of error message "error: path '/nix/store/0ccnxa25whszw7mgbgyzdm4nqc0zwnm8-source/flake.nix' does not exist" (https://determinate.systems/blog/changelog-determinate-nix-3...) I would not wish learning Nix from zero on my worst enemy, and I say that as someone who uses nix-darwin, devShells, deploy-rs and so on every day. The UX/DX is really bad, but nothing else comes close to its capabilities. Sorry for rant but without flakes I would not make it. | | |
| ▲ | entropie 5 hours ago | parent [-] | | > your flake is not committed or staged That has nothing to do with flakes. When I add a "module" to my repos its the same. I have to add it the git repos or nix does not "see" it. And yes, its pretty unintuitive. | | |
| ▲ | Hnus 4 hours ago | parent [-] | | It actually is specific to flakes. Classic nix commands can see untracked files just fine. Flake evaluation behaves differently because of how it decides which "scheme" to use: > If the directory is part of a Git repository, then the input will be treated as a `git+file:` URL, otherwise it will be treated as a `path:` url; This is why untracked or unstaged files disappear when using flakes: https://github.com/NixOS/nix/blob/ec6789f9dafce41011418fe6fc... |
|
|
|
|
|
| ▲ | grim_io 2 hours ago | parent | prev | next [-] |
| I may be an unreasonable outlier, but I absolutely refuse to learn a complex config language. YAML/TOML? These are the maximum of punishment I'm willing to deal with, as they are quite universal and useful in many situations. If you need a complex touring complete config, you better use a reasonably popular general purpose language, or I'm not touching it. |
| |
| ▲ | MangoToupe an hour ago | parent [-] | | > you better use a reasonably popular general purpose language Most languages are horrible at templating, so that's its own world of pain. | | |
| ▲ | grim_io an hour ago | parent [-] | | What kind of templating are we talking about? HTML or in general? If we take python, for example, you could use jinja for HTML and composition/inheritance for the general stuff. That's all django does, and it does it well. I don't see what nix is doing so much better. Prefer JS/TS? You can have JSX, which is superior in any way compared to this nix-based abomination. |
|
|
|
| ▲ | JoelMcCracken 6 hours ago | parent | prev | next [-] |
| neat! I've been moving my site over to heavily use emacs/org for the authoring format and nix for the tooling infrastructure. I'll keep this in mind as a possible tool to help; I don't precisely know what I may still need to do that won't be easily doable with emacs. |
|
| ▲ | rnhmjoj 5 hours ago | parent | prev | next [-] |
| There's a more cursed one here: https://rgbcu.be/blog/htmnix.
It hijacks the Nix search paths syntax (e.g. import <path> {}) to create html tags. |
| |
| ▲ | granra 4 hours ago | parent | next [-] | | I had seen a few of those `__findFile` hackery articles lately and did actually consider doing that but I think having a nice way of adding HTML attributes would've been clunky :p Edit: although looking at this article it seems to be supported. | |
| ▲ | JoelMcCracken 4 hours ago | parent | prev [-] | | oh my god, what a horrible but incredible idea |
|
|
| ▲ | badmonster 3 hours ago | parent | prev | next [-] |
| Using Nix for templating is wild but makes sense - you get reproducible builds, type checking, and function composition for free. The trade-off is portability and designer accessibility. Interesting niche: technical personal blogs where infrastructure-as-code mindset extends to content generation. |
|
| ▲ | NewJazz 6 hours ago | parent | prev | next [-] |
| Not to be confused with Nixtamal, the processed corn food. https://en.wikipedia.org/wiki/Nixtamalization |
| |
|
| ▲ | bigbuppo 3 hours ago | parent | prev | next [-] |
| I don't want to shit on this project, because that's not my intent. My biggest gripe with static site generators in general is that for some reason they require the author to write their pages in something other than plain HTML. It's literally a machine-readable format and yet they all want to mix json, yaml, or something with markdown. And "but the output html would overwrite the input html" isn't really an excuse since they all tend to output to a build directory. And before someone says, "well you can work on your dream static site generator yourself", rest assured, I am, but I'm also very lazy and usually stop once it gets to a "good enough" state for my own use, but isn't quite ready to share with others. |
| |
| ▲ | thangalin 3 hours ago | parent | next [-] | | > My biggest gripe with static site generators in general is that for some reason they require the author to write their pages in something other than plain HTML. Being the author of KeenWrite, a Markdown editor that uses YAML variables (for content and metadata), I'm biased, but here's my take: 1. Writing <p> tags for every paragraph gets tedious. 2. Markdown is succinct (**bold** vs. <strong>bold</strong>). 3. Content is easier to edit when not surrounded by angle brackets. 4. Content is more robust against markup gaffs (e.g., missing closing tags, tag typos). 5. HTML mixes structural markup with content, making design changes harder. 6. Markdown's simpler format is more portable to other output formats (PDF, ePub). 7. Markdown diffs are easier to review, and likely have fewer merge conflicts. 8. Non-technical contributors are more comfortable with Markdown. 9. Embedding metadata through meta tags is messier and harder to parse using raw HTML. Here are a couple of blog posts written in Markdown and converted to HTML using my software: * https://keenwrite.com/blog/2025/09/08/feature-matrix/ * https://keenwrite.com/blog/2025/10/15/creating-catchy-cover-... The user manual is a set of Markdown documents converted to PDF (note how the words TeX and ConTeXt and LaTeX are typeset; try to do that with HTML): * https://keenwrite.com/docs/user-manual.pdf | | |
| ▲ | bigbuppo an hour ago | parent [-] | | And this is the other big rub with static site generators... they start off as one person's strong opinions as The Right Way To Do It. And that's fine. 1. Not really
2. Get a better editor
3. Not really, or get a better editor
4. Get a better editor, implement error checking, and use HTML5
5. The idea is to use clean semantic html as the source document and stuff it into a presentation template
6. The source document is clean semantic html
7. Let's be real. 99.99999% of all static site generators are used by one person, generally technically proficient. Merge problems will only happen if you screw up. Also, most modern version control systems aren't storing deltas so merge hell isn't like it was back in the CVS era.
8. Get your non-technical people a better editor
9. Have you explained the quirks of YAML to a non-technical person in one of the Scandinavian countries like Sweden or False?
10. why isn't this formatting properly? |
| |
| ▲ | hnlmorg 3 hours ago | parent | prev | next [-] | | Forgive my ignorance here but if you want to write HTML then what do you gain from a static site generator? Couldn’t you just ‘cat’ your templates together with a shell script? | | |
| ▲ | bigbuppo an hour ago | parent [-] | | Starting with clean valid semantic HTML makes it a whole heck of a lot easier to preview in a web browser or editor with a preview feature and gives you quite a few editing options. Granted, there are now live markdown previews in some editors, so this is less of a concern than it was. However, you can easily toss in some CSS in there to make things a little nicer, while the typical markdown preview is going to look like Netscape 2. As for the templates... those are also HTML. You're just replacing the relevant part of the template's DOM with what you pulled from the source document. Same goes for any boxes on the page you need to stuff with generated content. Your index pages and blog lists are generated from the metadata and other items pulled from the relevant parts of the source documents using the favored html processsing library of the week. |
| |
| ▲ | granra 3 hours ago | parent | prev [-] | | Generally I think you have a point when making landing pages or things of that sort. I however basically only use static site generators for blogging and I think markdown/asciidoc/whatever + metadata is nicer for writing content than directly in HTML. I made nixtml and I take no offence :) | | |
| ▲ | bigbuppo an hour ago | parent [-] | | I think part of my take stems from the fact that I'm old enough to remember when SGML was supposed to solve all our problems. |
|
|
|
| ▲ | jebronie an hour ago | parent | prev [-] |
| this could have been a couple of lines of simple and maintainable php |