Background
Over the past week or two I've been working on a new web framework for Guile. This is based on the knowledge I've accumulated over the past 7 years working on things like the Guix Data Service, Guix Build Coordinator and Nar Herder, but also based on their code, as I've used Claude Code running Claude Opus 4.6 to build this (a large language model).
I've been hesitant to try coding with LLMs so far, I still think there's plenty of reasons to be, and others have done much more thinking about LLMs and the ethical and legal implications of using them to write software.
This blog post definitely isn't an argument for using these tools, but my "excuse" if you call it that, is that I wanted a Guile web framework to both use for existing and new projects, and this was an approach to get there faster and with the limited amount of motivation I have at the moment.
Introducing Safsaf
Safsaf, or Guile Safsaf if you prefer, is a web framework for Guile, built around using Guile Fibers and the Guile Knots web server.
It's only ~1800 lines of code, and the largest part is the router,
deciding which handler should respond to requests. The Guix Data
Service handled routing using match on the method and path
components, and this works pretty well, but for a long while I've
wanted a more declarative approach to routing. One where the code
could introspect the routes and generate links or even API
specifications.
Another important property of having routes as data is that it allows applying handler wrappers to the routes and the handlers that they reference. This is the model that Safsaf uses for middleware or functionality that you want to apply across some or all of the web service. Safsaf comes with a number of useful handler wrappers and functionality like logging and exception handling is implemented as handler wrappers.
I think it's also important what's not included. In comparison to GNU Artanis (which I did try using for the Guix Data Service many years ago), there's no inbuilt support for talking to databases, database migrations, a Model View Controller design or file based templates, and for all these things, I don't currently see a good reason to include support for them.
I would like to look at what can be included for internationalization support, as I think that's important. I'd also like to look at what's required for Server Sent Events (SSE) and WebSocket support, particularly as the Build Farm Front-end (BFFE) uses Server Sent Events.
The Safsaf Git repository includes a couple of example apps which you can run, a paste-bin and a blog site.
There's inevitably some issues with the code, and there's probably some issues with the design as well, but my hope is that this is a good starting point.
If you have any comments or questions, please reach out to me via email at mail@cbaines.net, raise an issue on Forgejo, or contact me on the Fediverse.
