[HN Gopher] Nixtml: Static website and blog generator written in...
___________________________________________________________________
Nixtml: Static website and blog generator written in Nix
Author : todsacerdoti
Score : 75 points
Date : 2025-12-02 14:54 UTC (8 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| JoelMcCracken wrote:
| 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.
| Y_Y wrote:
| 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 wrote:
| 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 wrote:
| 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-sou
| rce/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 wrote:
| > 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 wrote:
| 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/ec6789f9dafce41011418fe
| 6fc...
| MillironX wrote:
| > The flakes were the main UX/DX improvement for me. Before
| them I honestly could not do anything.
|
| Agreed. I think flakes are far more intuitive than
| channels. In a flake everything is declared in the repo
| it's used in. I still don't understand channels.
|
| For someone who's used to thinking in channels, I suppose
| flakes would be jarring. For someone (like me) who came
| from the world of Project.toml and package.json, flakes
| make a lot of sense.
| NewJazz wrote:
| Not to be confused with Nixtamal, the processed corn food.
|
| https://en.wikipedia.org/wiki/Nixtamalization
| hardwaregeek wrote:
| I was wondering if the logo would be a tortilla
| granra wrote:
| haha I'm afraid it was a total coincidence that it kind of
| looks like it :D
| mikepurvis wrote:
| 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 wrote:
| 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 wrote:
| 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 wrote:
| 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 wrote:
| 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 wrote:
| Out of curiousity, having never worked in the business of
| making websites, what would be accessible to a designer?
| Jinja2?
| mikepurvis wrote:
| 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 wrote:
| > 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...
| mikepurvis wrote:
| Groovy does something similar with MarkupTemplateEngine; I
| don't super care for it there either, at least as a
| mechanism for generating full webpages:
|
| https://docs.groovy-
| lang.org/docs/groovy-2.5.3/html/document...
|
| It can make a lot more sense as a way to prepare a smaller
| snippet of XML though, for example an xunit reponse.
| rnhmjoj wrote:
| 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.
| JoelMcCracken wrote:
| oh my god, what a horrible but incredible idea
| granra wrote:
| 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.
| bigbuppo wrote:
| 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.
| granra wrote:
| 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 wrote:
| 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.
| thangalin wrote:
| > 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 wrote:
| 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?
| bigbuppo wrote:
| Also... KeenWrite looks nice. You made the better editor for
| markdown.
| hnlmorg wrote:
| 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 wrote:
| 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.
|
| edit: I think I did a terrible job answering your question in
| my initial reply.
|
| Ultimately, a static site generator is doing what was the way
| that SGML was envisioned to function... you started with a
| simpler authoring document and passed it through a processing
| pipeline that generated a richer SGML document that was
| eventually output to some sort of output presentation form.
| My take is that instead of using yaml and markdown for the
| source documents you just use semantic html, and that
| templates just use everything that WHATWG has given us with
| modern HTML instead of that plus a template language.
| badmonster wrote:
| 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.
| grim_io wrote:
| 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 wrote:
| > 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 wrote:
| 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.
| jebronie wrote:
| this could have been a couple of lines of simple and maintainable
| php
___________________________________________________________________
(page generated 2025-12-02 23:01 UTC)