Arjen Wiersma

A blog on Emacs, self-hosting, programming and other nerdy things

I have been thinking about the effect of AI on how I perceive activities that I previously found enjoyable. Specifically the effect on how I perceive coding.

I made the mistake (looking at it in hindsight) of allowing AI to take over my critical thinking when it comes to coding. Like many I found the wonder of AI in that it was able to very quickly write entire programs for me. The downside of this was that I felt no connection to the code whatsoever.

The lose of connection meant I actually did not really care about the quality of it and if I would actually use it lateron. This was a new discovery for me, I always pride myself in the code I write and have been able to explain design choices a long time after I wrote it. With AI I find that even after a few minutes you struggle to explain the structure that was created.

Structured frameworks like Ruby on Rails lend themself extremely well to the use of AI as it actually requires you to follow a predetermined path to build things. Writing in plain languages (from Java to C++ and back to Clojure), away from structure will get you into a world of hurt really quickly.

This is, of course, due to the fact that AI simply does not care. It does not care about maintainability, quality, change, and any other quality metric you can think of. It will just rewrite the entire thing when it is necessary.

I found this out when working on some code for a workshop I gave. I had claude code writing the entire thing, but when the credits ran out and I had a bug while facing a deadline I found a lot of duplication, hard wired dependencies and overly complex solutions to relatively simple problems.

AI is not an engineer. An engineer designs for change, cares about quality and takes care of the code base. AI does non of that. Granted you can write complete specifications and guidelines in the details of these constraints, just as the old-skool analist would do. But did you get into coding to become a business analist writing detailed specifications? I did not.

So, did I stop using AI? No. I use it just like I used to use stack overflow, to understand how to fix something that was not obvious from documentation. The documentation now is also produced by AI, it reads API documentation from a project and provides me with use-case specific documentation, which is great.

I am slowly getting back to enjoying coding again, by keeping AI on the sideline.

There are many people that really enjoy the speed of AI development, Omarchy is one of those projects. Kudos to them for enjoying that. For me the fun is in actually figuring things out and enjoying the building proces.

So, I went shopping at the IKEA and ran into some really neat home automation gadgets. The Grillplats plug especially interested me as I would like to track power consumption of devices, and I did not yet find a good solution for that. One impulse buy later I was home with my new Grillplats plug.

Of course I did a quick google search in the store to see if it was compatible with home assistant, and I found some articles explaining how to add it to your setup. So I was unworried when I started tinkering. That soon changed.

It turns out that one requires a Thread border router for these devices. Of course IKEA sells them, but would I rather no add another device to my network. Home Assistant it self has a connector that can be used, the connect zbt-2, which just plugs into the USB port of my Home Assistant Green.

I bought the ZBT-2 and connected it. Followed the instructions on screen and configured it for Threads. This is a well thought out integration.

And that is it, right? No. Here are the gotcha's that I ran into and how I fixed them.

IPv6

Matter / Threads uses IPv6 to do their communication. That means that your network has to support IPv6. On my Amplifi Alien router I enabled IPv6 under Internet and made sure the DHCP was working.

On my laptop I was able to confirm IPv6 and mDNS (the way the devices find eachother) was working by running avahi-browser -a, it shows all the mDNS requests on the network.

New installations of Home Assistant Green will not have the next issue, but mine is a bit older. I had to enable IPv6 for the docker instance on the Home Assistant by running ha docker options --enable-ipv6=true in a terminal. I installed a SSH app on the Home Assistant for this purpose.

Provisioning the device / WiFi

I learned that when you provision the device with your phone, it first uses the phone (Android) to do a lot of heavy lifting, including transferring credentials for the Thread network, it then switches over to the Thread border router to do the rest, while your phone connects to the device over WiFi.

These devices use 2.4GHz to connect on the WiFi spectrum. My phone is modern and uses the 5GHz band if it is available (higher bandwidth), so it went from “Discovering Device”, “Generating Matter Credentials”, “Confirming connection to Thread network X” to “Could not connect to device”. The last bit stumped me for a long while, but then I turned off 5GHz on my WiFi and tried again. It finally worked.

Conclusion

The plug is working now. The 8 euro buy turned into a 53 euro buy, but I am monitoring my energy usage on the plug now :D.

I wonder how the IKEA device does this, a non-technical person would not be able to resolve the issues I've had to get it going. Perhaps it builds its own WiFi network for the devices? If you know, do send me a message!

My last post was quite a while back. In all honesty, the current state of affairs in coding land had me somewhat burned out on building things, AI is taking the pleasure out of actually thinking.

I switched jobs in April, which also took a mental toll... so I decided to step away from my hobby projects and workshops to just focus on that.

Now, 3 months later, I decided to reset the way I work with my projects. I have started focusing on a single project, a desktop based comic book collection tracker. It is written using Qt and C++.

I don't use any AI, except for finding things in the documentation (replacing stack overflow and search engines I guess), and I am starting to enjoy the process again. Removing AI from my workflow was quite easy; simply use Emacs and stay away from more elaborate tooling.

In the project that I was running last year up to April we had to use Jetbrains IDEA, and it is loaded with things to make you stop thinking critically. I think that has been the biggest “oh man, is this what life has become?” driver. Luckily I am now able to leave that behind me. Obviously I could've just not used that tooling, but when everyone in a project uses it, it becomes a given really. In hindsight I now no longer remember all the things I did with it, while I can still remember that specific piece of code that I struggled with before the AI systems took over the thinking process.

Luckily Emacs does not force anything on you. The biggest helper I use in Emacs is lsp-mode.

Qt in Emacs

Qt comes with its own IDE, qt-creator, surprisingly mostly AI free. It has good completion for all the qml based syntax. Luckily lsp-emacs provides a good interface here as well. A combination of cmake and some elisp makes everything work together.

CMake

Qt applications build using cmake, and as a result you can make it generate all the necessary configuration you need.

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(QT_QML_GENERATE_QMLLS_INI ON)

The compiler commands will generate compiler_commands.json, which lsp will pick up and configure itself with.

Generating .qmlls.ini based on your cmake configuration will configure the QML Lanuage Server.

Emacs

The only thing that is left is to configure Emacs to support qmlls.

(eval-after-load 'lsp-mode
  (lsp-register-client
   (make-lsp-client :new-connection (lsp-stdio-connection
                                     (lambda ()
                                       (executable-find "qmlls")))
                    :activation-fn (lsp-activate-on "qml")
                    :priority -1
                    :server-id 'qml-ls)))

Thats it.

I have several Linux distributions running, on my laptop I use Omarchy and on my desktop I have NixOS. I love the hyprland configuration of omarchy and how it works beautifully straight out of the box.

One thing I use, however, is automatic theme switching. When there is plenty of light during the day I like to use a white theme. At night, I like to use a dark theme. Most Desktop Environments have some way to configure this switch to happen automatically. On Omarchy it turns out to be trivial to implement as well.

First, we need a package that triggers a change based on time and location. The most simple package is darkman, a simple script that will trigger a change based on where you are. You can either hardcode the location in a configuration or use geoclue for it. I chose to do some hardcoding in the config as the times that I am not in my timezone with my laptop are very limited.

The configuration lives in /home/user/.config/darkman/config.yaml:

lat: 52.3
lng: 4.8
usegeoclue: false
portal: false

It will then look at /home/user/.local/share/darkman and execute every script in that directory with a paramter of light or dark. A small bash script toggles between the two themes.

#!/usr/bin/env bash

case "$1" in
dark) omarchy-theme-set vantablack ;;
light) omarchy-theme-set white ;;
default) exit 1 ;;
esac

Do not forget to make the script executable.

To enable the service use systemd. I would enable it as --user, that way you separate out your services from the system services.

systemctl --user enable --now darkman.service

It is easy to check if everything works by calling status on the service.

~ ❯ systemctl status --user darkman
● darkman.service - Framework for dark-mode and light-mode transitions.
     Loaded: loaded (/usr/lib/systemd/user/darkman.service; enabled; preset: enabled)
     Active: active (running) since Fri 2026-04-24 12:32:14 CEST; 4s ago
 Invocation: 5a923b9f1e3341d987ac4c32a344be07
       Docs: man:darkman(1)
   Main PID: 44124 (darkman)
      Tasks: 16 (limit: 18743)
     Memory: 12.3M (peak: 69.2M)
        CPU: 1.165s
     CGroup: /user.slice/user-1000.slice/user@1000.service/background.slice/darkman.service
             └─44124 /usr/bin/darkman run

Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF Running without XDG portal
Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF Not using geoclue; using static location
Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF Sundown comes first; so it's day time
Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF Wanted mode is mode=light
Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF No transition necessary
Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF Next sunrise time=2026-04-25T06:22:38.364+02:00
Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF Next sundown time=2026-04-24T20:54:17.853+02:00
Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF Will set an alarm for sundown
Apr 24 12:32:14 mini darkman[44124]: 12:32:14 INF Setting timer seconds=30123 nanoseconds=202749121
Apr 24 12:32:15 mini darkman[44124]: 12:32:15 INF Script exited OK name=omarchy

Yesterday I spent the day in the north of The Netherlands, in Groningen. A little over 150km drive from my house, The occassion? I was invited to hold my Offensive AI workshop at BSides Groningen. The event had 230 visitors, of which 29 chose to follow my workshop. That is an amazing number, and the room was packed. Together they completed 124 challenges and had 197 conversations with the bots in order to find the hidden codes.

img

The time for the presentation was a bit short, 90 minutes. But we managed to fully go through Part 1 and I left them with Part 2 as homework. The presentation is available.

10 out of 10 for a conference, it was small but had a great atmosphere. The quality of the talks was extremely high and I ran into a lot of familiar faces.

img

My AI workshop is gaining traction! My next stop will be at BSides Grunn on April 17th.

Last year, I had a very successful session at JFall 2025, where the workshop was rated as the 5th highest talk at the conference. While the session was excellent, I felt it necessary to enhance my platform a bit further.

In order to host the workshop on attacking AI systems, it is important to provide a way for these challenges to be done in a controlled environment. Although there are some options for quickly coding online tools using AI, I believed it essential to create a dedicated platform that enables participants to navigate through custom challenges.

My first iteration was a Spring Boot (Java) tool designed to host the challenges. While it was an adequate setup, the interaction with AI and presentation of the challenges felt somewhat clunky. The next iteration is a significant step forward in terms of features and usability. It is written in Ruby on Rails, the language is not only straightforward to use, but the framework also allows me to focus on the aspects that truly matter. A key advantage behind the scenes is deployability; I can easily implement changes to my production platform. With Rails, it takes just a single command to push changes to production, just like in the 90s.

So, what did I add to my workshop?

  • UX: light/dark mode, depending on the system settings
  • UX: conversations with AI instead of one-off messages
  • AI: support multiple models in case on outages
  • AI: allow user to select a more difficult model to see how their solution works
  • Admin: a better dashboard to track progress

Next up is to create some really nice custom challenges for the fine folks at BSides!

I came across Boris Buliga posting about Vulpea v2. In it he describes how vulpea is now a separated package from org-roam, and his motivations for it. I have been using vulpea functions for a while with my org-mode files, so I was very interested. More interestingly I came across his packages vui.el and vino. With vui.el you can make interfaces in Emacs using the same pattern as React, and vino is a wine management app built on top of vulpea.

Then I thought; can I make a comic book tracker in Emacs? I love comics, I have quite a collection, especially in the Spawn francise…

img

Yes, that is the short answer. The code is extremely messy, I just wanted to get something working, but the gist of it is that you can create notes with meta-tags and link them together. Below is the raw content of my Spawn #1 issue.

- serie :: [[id:89adef5d-a8a5-41c2-915e-feb2ea5d2fae][Spawn]]
- number :: 1
- description :: While a strange assailant stalks the city, ripping out human hearts, another otherworldly being arrives. As his mind reels, our tortured hero remembers that he struck a deal with the devil in order to return to his beloved wife - five years after his death. The man who was Al Simmons is no more. He has become Spawn.
- cover :: ./comics/collection/data/99/3c95fb-f873-4fef-b3e5-9682162a227b/cover.jpg
- credits :: [[id:91e551e7-a1ee-4776-b326-70e8e586c643][Chris Ulm]] (Editor In Chief), [[id:063713be-97ca-4d0d-b6db-e0aacf6e5bff][Dan Danko]] (Production), [[id:a73ee9d7-a2ba-4a15-8426-b186f70cf9b3][Ken Steacy]] (Cover), [[id:d7ab28dd-8240-4582-b8f6-bf2cba7a0e86][Reuben Rude]] (Colorist), [[id:4c9cc732-eb5d-454d-b524-09ac6973451a][Steve Oliff]] (Colorist), [[id:5beb711e-4b7f-434c-91d0-a8bf1cabff92][Todd McFarlane]] (Story, Penciller, Inker, Cover), [[id:5546604d-03c0-4539-9541-63baeb2880b7][Tom Orzechowski]] (Letterer), [[id:b25b0fa3-22bd-45c3-aa7b-3e3aab1da4c9][Wanda Kolomyjec]] (Editor)
- characters :: [[id:d1a1e2f2-b492-4025-9a41-6d58e7e44f26][Brock Fennel]], [[id:c6bd48dc-c3b1-45d8-a140-fb3808fcc4ac][Jason Wynn]], [[id:98278c4d-004a-4559-860c-2e1ebe4924c7][Malebolgia]], [[id:b6eff357-b385-4245-bd72-844cf4e599ba][Sam Burke]], [[id:88f71833-84c8-41dd-bd29-2419a7bbc7af][Spawn (Simmons)]], [[id:0c32d357-ed71-4998-b3b4-830841f49d8a][Twitch Williams]], [[id:304d0b1a-4c7b-4c01-99a9-ae53a720a518][Wanda Fitzgerald]]
- price :: 1.95
- store-date :: 1992-05-10
- cover-date :: 1992-05-01
- metron-id :: 55499
- teams :: [[id:35343aab-75a9-4509-b992-538bebecf2aa][Hellspawn]]
- title :: Questions, Part 1

I used the Metron Cloud API to retrieve the metadata about the comic, then I create linked notes for the credits, characters and teams. It is now possible to see what characters show up in an issue, and in what other issues they are seen. For instance, these are the issues that Angela shows up in:

  [Spawn 9]
  [Spawn 26]
  [Spawn 28]
  [Spawn 30]
  [Spawn 31]
  [Spawn 40]
  [Spawn 43]
  [Spawn 44]
  [Spawn 45]
  [Spawn 46]
  [Spawn 47]
  [Spawn 48]
  [Spawn 49]
  [Spawn 50]
  [Spawn 51]
  [Spawn 55]
  [Spawn 57]
  [Spawn 62]
  [Spawn 63]
  [Spawn 65]
  [Spawn 75]
  [Spawn 89]
  [Spawn 96]
  [Spawn 97]
  [Spawn 98]
  [Spawn 99]
  [Spawn 100]
  [Spawn 101]

I love this setup, it gives me what I want in terms of the content and the accessibility through Emacs that is not a CSV. So I will build it out to a full app.

I like my modus themes for Emacs, and I thought it would be fun to bring them to my writefreely blog as well.

Below is the CSS you can drop in your Customize, it will automatically switch between light and dark variants.

/* =====================
   WriteFreely Modus Theme
   Auto light/dark via prefers-color-scheme
   ===================== */

/* Modus Operandi (Light) — default */
:root {
  --bg:          #ffffff;
  --bg-alt:      #f2f2f2;
  --surface:     #e8e8e8;
  --border:      #c6c6c6;
  --text:        #000000;
  --text-muted:  #595959;
  --text-faint:  #8a8a8a;
  --accent:      #8f0075;   /* Modus magenta */
  --accent-dim:  #c04fa8;
  --link:        #0031a9;   /* Modus blue */
  --link-hover:  #003497;
  --code-fg:     #005e00;   /* Modus green for code */
}

/* Modus Vivendi (Dark) — activated by OS dark mode */
@media (prefers-color-scheme: dark) {
  :root {
    --bg:          #000000;
    --bg-alt:      #1e1e1e;
    --surface:     #2a2a2a;
    --border:      #444444;
    --text:        #ffffff;
    --text-muted:  #ababab;
    --text-faint:  #6a6a6a;
    --accent:      #feacd0;   /* Modus Vivendi magenta */
    --accent-dim:  #a04080;
    --link:        #79a8ff;   /* Modus Vivendi blue */
    --link-hover:  #a8c7ff;
    --code-fg:     #44bc44;   /* Modus Vivendi green */
  }
}

/* Base */
body {
  background-color: var(--bg);
  color: var(--text);
  font-family: Georgia, serif;
  font-size: 18px;
}

/* Navigation / Header */
header, nav#blog-title {
  background-color: var(--bg);
  border-bottom: 1px solid var(--border);
}

header nav a,
nav#blog-title a {
  color: var(--text-muted);
  text-decoration: none;
  letter-spacing: 0.04em;
  font-size: 0.85rem;
  text-transform: uppercase;
}

header nav a:hover,
nav#blog-title a:hover {
  color: var(--accent);
}

/* Main content area */
section, #wrapper, #collection {
  max-width: 900px !important;
  margin: 0 auto;
  padding: 2rem 1.5rem;
}

/* Post / Article */
article, .post {
  background: transparent;
  max-width: 900px !important;
}

article {
  background: transparent;
  max-width: 900px !important;
}

/* Headings */
h1, h2, h3, h4, h5, h6 {
  color: var(--text) !important;
  font-family: Georgia, serif !important;
  font-weight: 700 !important;
  line-height: 1.3 !important;
  padding-top: 1em;
}

h1.post-title a,
h2.post-title a,
h1 a, h2 a, h3 a {
  color: var(--text) !important;
}

h1.post-title a:hover,
h2.post-title a:hover,
h1 a:hover, h2 a:hover, h3 a:hover {
  color: var(--accent) !important;
}

/* Links */
a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-color: var(--accent-dim);
  text-underline-offset: 3px;
  transition: color 0.15s ease;
}

a:hover {
  color: var(--link-hover);
  text-decoration-color: var(--link-hover);
}

/* Paragraphs */
p {
  color: var(--text) !important;
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
}

.description {
  color: var(--text) !important;
  text-align: center;
}

/* Blockquote */
blockquote {
  border-left: 3px solid var(--accent-dim);
  margin: 1.5em 0;
  padding: 0.5em 1.5em;
  color: var(--text-muted);
  font-style: italic;
  background: var(--bg-alt);
}

/* Code */
code {
  font-family: 'Courier New', monospace !important;
  font-size: 0.85em !important;
  background: var(--surface) !important;
  color: var(--code-fg) !important;
  border: 0px !important;
  padding: 0.15em 0.4em !important;
}

pre {
  background: var(--surface) !important;
  padding: 1.2em 1.5em !important;
  overflow-x: auto !important;
}

pre code {
  background: transparent !important;
  padding: 0 !important;
  font-size: 0.9em !important;
  color: var(--code-fg) !important;
}

.post pre, .post code,
article pre, article code,
#post pre, #post code {
  background: var(--surface) !important;
  color: var(--code-fg) !important;
}

/* Horizontal rule */
hr {
  border: none;
  border-top: 1px solid var(--border);
}

/* Post metadata / date */
.post-meta, time, .date {
  color: var(--text-faint);
  font-size: 0.82rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* Post list (index page) */
.post-listing, #collection .posts {
  list-style: none;
  padding: 0;
}

.post-listing li, .post-list-item {
  border-bottom: 1px solid var(--border);
  padding: 1.2em 0;
}

/* Footer */
footer {
  border-top: 1px solid var(--border);
  color: var(--text-faint);
  font-size: 0.82rem;
  padding: 2rem 0;
  text-align: center;
}

footer a {
  color: var(--text-muted);
}

/* Read more link */
.read-more {
  color: var(--accent);
  font-size: 0.875rem;
  text-decoration: none;
  letter-spacing: 0.03em;
}

.read-more:hover {
  color: var(--link-hover);
}

/* Images */
img {
  max-width: 100%;
  height: auto;
  border-radius: 3px;
}

/* Selection */
::selection {
  background: var(--accent-dim);
  color: #ffffff;
}

/* Scrollbar (Webkit) */
::-webkit-scrollbar {
  width: 8px;
}
::-webkit-scrollbar-track {
  background: var(--bg);
}
::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--text-faint);
}

Finished in February

I finished reading/listening to the follow books:

  • Ewout: avonturen en inzichten van een eigenzinnige programmamaker
  • Het wordt ook steeds gekker. Stories by Lieke Hesters
  • De tindermoord: een swipe naar rechts wordt haar doodvonnis, het dramatische verhaal van Mieke Oort

Read this year

  • Je bent wat je doet by Ray Klaassens; a book about taking ownership in your life/work/everything
  • Nu of nooit by Dai Carter; a book on mental strength and tools how to stay the course in difficult times
  • Explosief; a short story by writing collective Crime Squad

Currently reading/listening

Currently reading The secret of secrets by Dan Brown.

Listening to Project Hail Mary by Andy Weir.

For English, see below.

Elke dag worden we opnieuw geconfronteerd met slecht nieuws op het front van digitale autonomie, zoals de Belastingdienst die alle btw-systemen gaat outsourcen. Deze drang om alles op Amerikaanse systemen te zetten komt natuurlijk voort uit gemak en vertrouwdheid.

Tijdens ons digitale leven, dat meestal begint op school, worden we al kennisgemaakt met Big Tech-oplossingen: van Chromebooks met educatieve software tot Microsoft 365 (of tegenwoordig de Copilot-app), waarin essays en presentaties worden gemaakt. Je komt van school af met een grote vertrouwdheid met precies deze technologieën, die vervolgens ook ons beroepsleven blijven begeleiden.

Het Nederlandse bedrijfsleven hecht veel waarde aan gecertificeerd personeel, en dat speelt Microsoft natuurlijk uitstekend in de kaart. Vanaf het moment dat je op school leert werken met Microsoft-producten word je al klaargestoomd om een gecertificeerde professional te worden. Dit heeft ertoe geleid dat bijna alle Nederlandse gemeenten op Microsoft draaien (kaart).

Het hoeft echter niet zo te gaan. We kunnen zelf betere keuzes maken op het gebied van persoonlijke computing. Het is helemaal niet nodig om een Windows- of Apple-computer te gebruiken, er zijn daadwerkelijk alternatieven.

Vrijheid met een personal computer

De “bicycle for the mind”, zoals Steve Jobs de pc noemde, is inmiddels meer een “prison cell for the mind” geworden. Je krijgt enkel voorgeschoteld wat iemand “correct genoeg” acht. Als app-ontwikkelaar moet je door allerlei hoepels springen om in de verschillende stores terecht te komen.

Gelukkig is er het open internet, al benaderen we dat weer via Big Tech. We zien enkel wat door juist deze bedrijven goed geïndexeerd is. Daarom bouwde ik tsjo.ch, een index van onafhankelijke bronnen.

Er is een oplossing: Linux. Voor de meeste mensen zou ik Ubuntu met KDE of Fedora met KDE aanraden.

De reden waarom ik KDE aanraad en niet GNOME, een andere dominante desktopomgeving, is simpelweg dat de KDE-ervaring dicht bij de vertrouwde omgeving van de meeste gebruikers ligt.

Vrijheid in de enterprise

Linux zou voor veel organisaties prima kunnen werken. Binnen de enterprise is er al jarenlang een beweging om applicaties web-based te maken, en om een browser te draaien is echt geen speciale Windows-versie nodig.

Authenticatie binnen de enterprise kan gelukkig al jaren met LDAP-gebaseerde oplossingen worden geregeld.

Het is alleen minder gepolijst dan de Microsoft-oplossingen. Bert Hubert beschrijft dit treffend: in Europa hebben we allemaal losse onderdelen in plaats van één samenhangend geheel.

Maar als we al die losse stukjes nooit gaan gebruiken, zal er ook nooit één groot geheel ontstaan.


Digital autonomy

Every day we are confronted with bad news on the front of digital autonomy, such as the Dutch Tax Authority outsourcing all its VAT systems to American management. This urge to move everything onto American systems naturally stems from convenience and familiarity.

During our digital lives, which usually begin at school, we are already introduced to Big Tech solutions: from Chromebooks with educational software to Microsoft 365 (or nowadays the Copilot app), in which essays and presentations are created. You leave school with a deep familiarity with precisely these technologies, which then continue to follow us into our professional lives.

Dutch businesses place great value on certified personnel, and Microsoft plays into this perfectly. From the moment you learn to work with Microsoft products at school, you are already being groomed to become a certified professional. This has led to almost all Dutch municipalities running on Microsoft (map).

It does not have to be this way. We can make better choices ourselves when it comes to personal computing. There is absolutely no need to use a Windows or Apple computer, there are genuine alternatives.

Freedom with a personal computer

The “bicycle for the mind”, as Steve Jobs called the PC, has by now become more of a “prison cell for the mind”. You are only offered what someone deems “correct enough”. As an app developer, you have to jump through countless hoops to get into the various stores.

Fortunately, there is the open internet, though we access it once again through Big Tech. We only see what these very companies have indexed well. That is why I built tsjo.ch, an index of independent resources.

There is a solution: Linux. For most people I would recommend Ubuntu with KDE or Fedora with KDE.

The reason I recommend KDE over GNOME, another dominant desktop environment, is simply that the KDE experience is closest to the familiar environment most users already know.

Freedom in the enterprise

Linux could work perfectly well for many organisations. Within the enterprise, there has been a push for years to make applications web-based, and running a browser does not require any special version of Windows.

Authentication within the enterprise has fortunately been handled with LDAP-based solutions for many years.

It is simply less polished than Microsoft's offerings. Bert Hubert describes this well: in Europe we all have separate components instead of one coherent whole.

But if we never start using all those separate pieces, one unified whole will never emerge.