skip to the content

Dev

The FREE stack - My Tech Radar

· 40 minutes

The FREE stack, ring by ring — what I trust, and inside each ring, the layers it lands in.


AdoptAdoptAdoptAdoptAdoptAdoptTrialTrialTrialTrialTrialTrialAssessAssessAssessAssessAssessAssess️ Deprecate️ Deprecate️ Deprecate️ Deprecate️ Deprecate️ DeprecateGuile Scheme and Lisps in general — Adopt ring, LanguagesGuile Scheme and Lisps in…Emacs Lisp — Adopt ring, LanguagesEmacs LispJavaScript (vanilla) — Adopt ring, LanguagesJavaScript (vanilla)Rust — Adopt ring, LanguagesRustC — Adopt ring, Languages, new since the last revision. the two desktop apps, LambDock and Heks Toon, are C with GTK4 around a Guile engine, and nothing above them needs a heavier languageCGNU Artanis — Adopt ring, Frameworks & UIGNU ArtanisGTK4 Libadwaita — Adopt ring, Frameworks & UIGTK4 LibadwaitaOlive CSS for all serious web projects (utility class vanilla CSS) — Adopt ring, Frameworks & UIOlive CSS for all serious web…Hygguile UI components (batteries included Guile Scheme UI framework built on Olive CSS) — Adopt ring, Frameworks & UIHygguile UI components…SQLite — Adopt ring, ️ Data & StorageSQLitePostgreSQL — Adopt ring, ️ Data & StoragePostgreSQLPlain SQL queries — Adopt ring, ️ Data & StoragePlain SQL queriesHetzner Storage Volumes with Cron-job based backups and rsync — Adopt ring, ️ Data & StorageHetzner Storage Volumes with…Mutastructura — Adopt ring, ️ Data & Storage, new since the last revision. migrations decreed as Lisp and applied incrementally, so a schema change is a file in the repo rather than a script someone ran onceMutastructuraGNU Guix — Adopt ring, ️ Tools & EnvironmentGNU GuixEmacs — Adopt ring, ️ Tools & EnvironmentEmacsOrg mode — Adopt ring, ️ Tools & EnvironmentOrg modeMaak build tool and command runner — Adopt ring, ️ Tools & EnvironmentMaak build tool and command…Veritas test framework (idiomatic unit, integration and black-box testing framework powered by Lisp - Guile Scheme) — Adopt ring, ️ Tools & EnvironmentVeritas test framework…Scriba structured logging framework (modular log routing, formatting, and filtering, allowing developers to generate human-readable console logs during development and machine-readable logs for production environments) — Adopt ring, ️ Tools & EnvironmentScriba structured logging…Woodpecker CI/CD — Adopt ring, ️ Tools & Environment. the CI that replaced the Jenkins pipelines I used to maintainWoodpecker CI/CDNix Flakes — Adopt ring, ️ Tools & EnvironmentNix FlakesNix dev shells — Adopt ring, ️ Tools & EnvironmentNix dev shellsMeson and Ninja — Adopt ring, ️ Tools & Environment, new since the last revision. what builds the C desktop apps, with Maak driving the steps around itMeson and NinjaSift — Adopt ring, ️ Tools & Environment, new since the last revision. the Lisp formatter, linter and language server that never loses a byte; every Scheme repo of mine is linted through itSiftByggsteg — Adopt ring, ️ Tools & Environment, new since the last revision. pipelines described as a list in Lisp, and the CI that runs themByggstegCustom low-power green VPS (Hetzner) — Adopt ring, Platforms & DeliveryCustom low-power green VPS…Codeberg — Adopt ring, Platforms & Delivery. free software's own forge, and the home of every project of mineCodebergDocker images as the delivery unit — Adopt ring, Platforms & Delivery, new since the last revision. every repo builds one and a compose file brings the stack up, so the server needs a container runtime rather than a list of install stepsDocker images as the delivery…Authorization and Authentication with Bewaking tokens as cookies — Adopt ring, ️ Practice & CraftAuthorization and…Guix Manifests — Adopt ring, ️ Practice & CraftGuix ManifestsGuix dev shells — Adopt ring, ️ Practice & CraftGuix dev shellsHexagonal architecture / ports and adapters — Adopt ring, ️ Practice & Craft, closer to the middle than before. the boundary earns its keep wherever the domain is the complicated part; the Hexagon of Doom is the case where it is notHexagonal architecture /…A Guix manifest and a Nix flake in the same repo — Adopt ring, ️ Practice & Craft, new since the last revision. the toolchain described twice, so either package manager opens a shell that matches the buildA Guix manifest and a Nix…Guile embedded in C and GTK4 — Trial ring, Languages, closer to the middle than before. the dock Wayland was waiting for, with a Lisp engine inside a native appGuile embedded in C and GTK4Kotlin — Trial ring, Languages, new since the last revision. symbanta, where the JVM's libraries and compile-time checks pay for the ceremonyKotlinPython — Trial ring, Languages, new since the last revision. the icon tooling (icns2linux, skeu-icons), where Pillow and numpy do the workPythonSpring Boot — Trial ring, Frameworks & UI, new since the last revision. symbanta's HTTP layer: validation, security, JPA and Actuator out of the box, at the price of a framework that decides a great deal for youSpring BootReact 19 with Vite — Trial ring, Frameworks & UI, new since the last revision. symbanta's dashboard, and the one place a client-side framework still earns its keep; everything new is server-renderedReact 19 with ViteFlyway — Trial ring, ️ Data & Storage, new since the last revision. migrations for symbanta's PostgreSQL, versioned beside the code that reads those tablesFlywayPodman — Trial ring, ️ Tools & Environment, closer to the middle than before. daemonless, root-less containers that stay under my own controlPodmanHyprland — Trial ring, ️ Tools & Environment, closer to the middle than before. the Wayland compositor I actually use daily, after SwayFX taught me compositor scriptingHyprlandDeepSeek — Trial ring, ️ Tools & Environment, new since the last revision. an LLM I keep on a short leash: it drafts and reviews, a human decides, and nothing it writes ships unreadDeepSeekMaven with its wrapper — Trial ring, ️ Tools & Environment, new since the last revision. what the one JVM project needs; Maak still drives everything around itMaven with its wrapperOpenAPI as the contract — Trial ring, ️ Tools & Environment, new since the last revision. guile-openapi-generator on the Scheme side and orval on the dashboard's, so neither hand-writes the other's typesOpenAPI as the contractSelf-hosted Woodpecker runners on the same VPS — Trial ring, Platforms & Delivery, closer to the middle than before. CI that never leaves infrastructure I controlSelf-hosted Woodpecker…Server-side rendering over client-side JavaScript — Trial ring, ️ Practice & Craft, closer to the middle than before. pages that work before, and without, a megabyte of frameworkServer-side rendering over…This very site as a single Org tree — Trial ring, ️ Practice & Craft, closer to the middle than before. prose, build script and metadata in one plain-text sourceThis very site as a single…Parsing Expression Grammar in Scheme with — Trial ring, ️ Practice & Craft, closer to the middle than before. how OrgWebAlchemy turns Org into HTML without a parser generatorParsing Expression Grammar in…Testcontainers and Kotest — Trial ring, ️ Practice & Craft, new since the last revision. the JVM suite runs against a real PostgreSQL in a container, beside the fast testsTestcontainers and KotestGuile Hoot — Assess ring, Languages. Scheme compiled to WebAssemblyGuile HootZig — Assess ring, LanguagesZigHare — Assess ring, LanguagesHareForgejo — Assess ring, ️ Tools & Environment. a self-hosted forge for code I want to keep closer than Codeberg's public instanceForgejoGuix Home — Assess ring, ️ Tools & Environment. one declarative description of the machine I actually work onGuix HomeGuix System images on AArch64 — Assess ring, Platforms & Delivery, closer to the middle than before. a machine I can describe, build and roll back, on hardware that is not x86Guix System images on AArch64Guix System as the whole server, not just the toolchain — Assess ring, Platforms & DeliveryGuix System as the whole…Property-based testing — Assess ring, ️ Practice & Craft. describing the invariant instead of the exampleProperty-based testingReproducible CI with `guix time-machine` — Assess ring, ️ Practice & CraftReproducible CI with `guix…Haskell — ️ Deprecate ring, Languages, further from the middle than before. as beautiful and powerful as it is, it's simply too complex for 9/10 use-casesHaskellScala — ️ Deprecate ring, LanguagesScalaCommon Lisp — ️ Deprecate ring, Languages. rather use Scheme if possibleCommon LispTypeScript — ️ Deprecate ring, LanguagesTypeScriptSvelte — ️ Deprecate ring, Frameworks & UISvelteServant (Haskell), API as a type — ️ Deprecate ring, Frameworks & UIServant (Haskell), API as a…ZIO (Scala) — ️ Deprecate ring, Frameworks & UIZIO (Scala)Tailwind CSS — ️ Deprecate ring, Frameworks & UI, new since the last revision. the dashboard's utility classes; Olive CSS says the same things with no build stepTailwind CSSMySQL — ️ Deprecate ring, ️ Data & StorageMySQLJenkins — ️ Deprecate ring, ️ Tools & Environment, further from the middle than before. shared-library pipelines and Groovy DSLs, traded away for a thinner agentJenkinsAmazon AWS — ️ Deprecate ring, Platforms & DeliveryAmazon AWS

Rings

Layers

Each blip links to the entry it stands for; the full catalogue is below, under the rings it belongs to. On a narrow screen the drawing is wider than the page, so it pans.

The rings #

Adopt
proven in daily work, and the default for anything new.
Trial
running on real projects, not yet a default.
Assess
worth a prototype, and no commitment yet.
Deprecate
actively discouraged for new work.

A name in parentheses — (new), (moved in), (moved out) — says what changed since the last revision; a note after a dash says why.

What FREE means #

F — Functional
declarative, predictable systems with clear effects.
R — REPL
code evaluated on the running system, with no write-compile-test lag.
E — Extensible
a stack built to scale into flexible, extensible systems.
E — Environment Control
the whole lifecycle under my own control: no hidden telemetry, no paywalls, one-command self-hosting.

✅ Adopt #

🧬 Languages #

  • Guile Scheme and Lisps in general
  • Emacs Lisp
  • JavaScript (vanilla)
  • Rust
  • C (new) — the two desktop apps, LambDock and Heks Toon, are C with GTK4 around a Guile engine, and nothing above them needs a heavier language

🎨 Frameworks & UI #

🗃️ Data & Storage #

  • SQLite
  • PostgreSQL
  • Plain SQL queries
  • Hetzner Storage Volumes with Cron-job based backups and rsync
  • Mutastructura (new) — migrations decreed as Lisp and applied incrementally, so a schema change is a file in the repo rather than a script someone ran once

🧰️ Tools & Environment #

  • GNU Guix
  • Emacs
  • Org mode
  • Maak build tool and command runner
  • Veritas test framework (idiomatic unit, integration and black-box testing framework powered by Lisp - Guile Scheme)
  • Scriba structured logging framework (modular log routing, formatting, and filtering, allowing developers to generate human-readable console logs during development and machine-readable logs for production environments)
  • Woodpecker CI/CD — the CI that replaced the Jenkins pipelines I used to maintain
  • Nix Flakes
  • Nix dev shells
  • Meson and Ninja (new) — what builds the C desktop apps, with Maak driving the steps around it
  • Sift (new) — the Lisp formatter, linter and language server that never loses a byte; every Scheme repo of mine is linted through it
  • Byggsteg (new) — pipelines described as a list in Lisp, and the CI that runs them

🌐 Platforms & Delivery #

  • Custom low-power green VPS (Hetzner)
  • Codeberg — free software’s own forge, and the home of every project of mine
  • Docker images as the delivery unit (new) — every repo builds one and a compose file brings the stack up, so the server needs a container runtime rather than a list of install steps

⚙️ Practice & Craft #

  • Authorization and Authentication with Bewaking tokens as cookies
  • Guix Manifests
  • Guix dev shells
  • Hexagonal architecture / ports and adapters (moved in) — the boundary earns its keep wherever the domain is the complicated part; the Hexagon of Doom is the case where it is not
  • A Guix manifest and a Nix flake in the same repo (new) — the toolchain described twice, so either package manager opens a shell that matches the build

🧪 Trial #

🧬 Languages #

  • Guile embedded in C and GTK4 (moved in) — the dock Wayland was waiting for, with a Lisp engine inside a native app
  • Kotlin (new) — symbanta, where the JVM’s libraries and compile-time checks pay for the ceremony
  • Python (new) — the icon tooling (icns2linux, skeu-icons), where Pillow and numpy do the work

🎨 Frameworks & UI #

  • Spring Boot (new) — symbanta’s HTTP layer: validation, security, JPA and Actuator out of the box, at the price of a framework that decides a great deal for you
  • React 19 with Vite (new) — symbanta’s dashboard, and the one place a client-side framework still earns its keep; everything new is server-rendered

🗃️ Data & Storage #

  • Flyway (new) — migrations for symbanta’s PostgreSQL, versioned beside the code that reads those tables

🧰️ Tools & Environment #

  • Podman (moved in) — daemonless, root-less containers that stay under my own control
  • Hyprland (moved in) — the Wayland compositor I actually use daily, after SwayFX taught me compositor scripting
  • DeepSeek (new) — an LLM I keep on a short leash: it drafts and reviews, a human decides, and nothing it writes ships unread
  • Maven with its wrapper (new) — what the one JVM project needs; Maak still drives everything around it
  • OpenAPI as the contract (new) — guile-openapi-generator on the Scheme side and orval on the dashboard’s, so neither hand-writes the other’s types

🌐 Platforms & Delivery #

  • Self-hosted Woodpecker runners on the same VPS (moved in) — CI that never leaves infrastructure I control

⚙️ Practice & Craft #

  • Server-side rendering over client-side JavaScript (moved in) — pages that work before, and without, a megabyte of framework
  • This very site as a single Org tree (moved in) — prose, build script and metadata in one plain-text source
  • Parsing Expression Grammar in Scheme with (ice-9 peg) (moved in) — how OrgWebAlchemy turns Org into HTML without a parser generator
  • Testcontainers and Kotest (new) — the JVM suite runs against a real PostgreSQL in a container, beside the fast tests

🔍 Assess #

🧬 Languages #

🧰️ Tools & Environment #

  • Forgejo — a self-hosted forge for code I want to keep closer than Codeberg’s public instance
  • Guix Home — one declarative description of the machine I actually work on

🌐 Platforms & Delivery #

  • Guix System images on AArch64 (moved in) — a machine I can describe, build and roll back, on hardware that is not x86
  • Guix System as the whole server, not just the toolchain

⚙️ Practice & Craft #

  • Property-based testing — describing the invariant instead of the example
  • Reproducible CI with `guix time-machine`

🗑️ Deprecate #

🧬 Languages #

  • Haskell (moved out) — as beautiful and powerful as it is, it’s simply too complex for 9/10 use-cases
  • Scala
  • Common Lisp — rather use Scheme if possible
  • TypeScript

🎨 Frameworks & UI #

  • Svelte
  • Servant (Haskell), API as a type
  • ZIO (Scala)
  • Tailwind CSS (new) — the dashboard’s utility classes; Olive CSS says the same things with no build step

🗃️ Data & Storage #

  • MySQL

🧰️ Tools & Environment #

  • Jenkins (moved out) — shared-library pipelines and Groovy DSLs, traded away for a thinner agent

🌐 Platforms & Delivery #

  • Amazon AWS