<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>akos.ma</title><link>https://akos.ma/</link><description>Recent content on akos.ma</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 05 Jun 2026 00:00:00 +0200</lastBuildDate><atom:link href="https://akos.ma/index.xml" rel="self" type="application/rss+xml"/><item><title>Conselho</title><link>https://akos.ma/blog/conselho/</link><pubDate>Fri, 05 Jun 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/conselho/</guid><description> &lt;p>I always share stuff from Argentina, but after listening to &lt;a href="https://www.youtube.com/watch?v=sdvZkPP0aUc">this song&lt;/a> you might want to head towards Brazil instead.&lt;/p></description><content:encoded><![CDATA[ <p>I always share stuff from Argentina, but after listening to <a href="https://www.youtube.com/watch?v=sdvZkPP0aUc">this song</a> you might want to head towards Brazil instead.</p>
<p>I&rsquo;ve been listening to it in a loop for the last few days. It&rsquo;s like having a streaming service of sunny weather in your ears. I thought you could use some sun, too. It struck a chord in me. It made me feel good. It made me smile. I felt thankful.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/sdvZkPP0aUc?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>Here goes a good translation of the lyrics in English via some IA over there:</p>
<blockquote>
<p>(Let it go) <br>
Let go of that low mood <br>
Raise your head and face evil <br>
Acting this way will be vital for your heart <br>
Because in every experience you learn a lesson <br>
I&rsquo;ve already suffered for loving like this <br>
I dedicated myself but it was all in vain <br>
<br>
(Why?) <br>
Why lament? <br>
If in your life you can find <br>
Someone who loves you with all their strength and passion <br>
Then the pain will subside <br>
<br>
(You have to fight) <br>
You have to fight <br>
Don&rsquo;t get discouraged <br>
Just give yourself <br>
To someone who deserves you <br>
I&rsquo;m not giving or selling <br>
As the saying goes <br>
My advice is to see you happy <br>
<br>
(repeat) <br>
<br>
Lala-laia <br>
Lala-laia laia, lala-laia laia, lala-laia, laia-laia-laia <br>
I&rsquo;m not giving or selling <br>
As the saying goes <br>
My advice is to see you happy <br>
My advice is to see you happy <br>
My advice is to see you happy</p>
</blockquote>
<p>I&rsquo;ve never learned Portuguese, so it&rsquo;s uncanny how much I could understand (70%, easily) of the lyrics just on the first try. The original goes below, just for the sake of beauty. Brazilian Portuguese is such a beautifully sounding language, it&rsquo;s almost obscene.</p>
<blockquote>
<p>(Deixe de lado) <br>
Deixe de lado esse baixo astral <br>
Ergua a cabeça enfrente o mal <br>
Agindo assim será vital para o seu coração <br>
É que em cada experiência se aprende uma lição <br>
Eu já sofri por amar assim <br>
Me dediquei mas foi tudo em vão <br>
<br>
(Pra que?) <br>
Pra que se lamentar? <br>
Se em sua vida pode encontrar <br>
Quem te ame com toda força e ardor <br>
Assim sucumbirá a dor <br>
<br>
(Tem que lutar) <br>
Tem que lutar <br>
Não se abater <br>
Só se entregar <br>
A quem te merecer <br>
Não estou dando nem vendendo <br>
Como o ditado diz <br>
O meu conselho é pra te ver feliz <br>
<br>
(…) <br>
<br>
Lala-laia <br>
Lala-laia laia, lala-laia laia, lala-laia, laia-laia-laia <br>
Não estou dando e nem vendendo <br>
Como o ditado diz <br>
O meu conselho é pra te ver feliz <br>
O meu conselho é pra te ver feliz <br>
O meu conselho é pra te ver feliz</p>
</blockquote>
]]></content:encoded></item><item><title>What's in Your Container? Securing the Software Supply Chain Without Slowing Down</title><link>https://akos.ma/blog/whats-in-your-container-securing-the-software-supply-chain-without-slowing-down/</link><pubDate>Fri, 29 May 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/whats-in-your-container-securing-the-software-supply-chain-without-slowing-down/</guid><description> &lt;p>How do we secure massive, complex supply chains without slowing your developers down to a crawl? This talk provides a simple preview to Red Hat&amp;rsquo;s Trusted Software Supply Chain, based on three pillars: Transparency through the Trusted Profile Analyzer; Identity, thanks to the Trusted Artifact Signer; and Guardrails, with the Advanced Cluster Security for Kubernetes.&lt;/p></description><content:encoded><![CDATA[ <p>How do we secure massive, complex supply chains without slowing your developers down to a crawl? This talk provides a simple preview to Red Hat&rsquo;s Trusted Software Supply Chain, based on three pillars: Transparency through the Trusted Profile Analyzer; Identity, thanks to the Trusted Artifact Signer; and Guardrails, with the Advanced Cluster Security for Kubernetes.</p>
<p>Talk presented at the 2026 Red Hat Summit Connect Switzerland event on January 14th, 2026.</p>
<h2 id="introduction">Introduction</h2>
<p>Welcome to this presentation titled &ldquo;What&rsquo;s in your Container? Securing the Supply Chain without Slowing Down&rdquo;. This talk was first presented at the 2026 Red Hat Summit Connect Switzerland event in January 14th, 2026.</p>
<p>My name is Adrian Kosmaczewski, and I am a Senior Architect at Red Hat Switzerland.</p>
<h2 id="the-black-box-problem">The &ldquo;Black Box&rdquo; Problem</h2>
<p>Let us talk about the &ldquo;Black Box&rdquo; problem.</p>
<p>Imagine, for a moment, that you walk into a grocery store to buy a frozen lasagna for your family dinner. You pick up the box from the freezer aisle. You toss it in your cart. You trust it. You assume the meat isn&rsquo;t spoiled. You assume the factory where it was made followed strict health codes.</p>
<p>You assume that the list of ingredients printed on the back (flour, tomatoes, beef, etc.) is actually what is inside the box. You trust the supply chain implicitly because there are regulations and checks in place to keep you safe.</p>
<p>Now, let’s pivot and look at how we build software today.</p>
<p>Modern software development has fundamentally changed. We don’t really &ldquo;write&rdquo; code from scratch anymore; we assemble it. We are manufacturing applications on an industrial scale. We take a database from here, a web framework from there, an authentication library from somewhere else, and we glue it all together with a thin layer of our own business logic.</p>
<p>The data backs this up. According to the latest &ldquo;Open Source Security and Risk Analysis Report&rdquo; by Synopsys, 96% of all commercial codebases contain open source components. Furthermore, 84% of those codebases contain at least one known vulnerability. We aren&rsquo;t just using a little bit of open source; our applications are essentially composed of it.</p>
<p>This is fantastic for speed. It allows us to innovate at a pace that was impossible ten years ago. It’s why startups can disrupt giants. But it is absolutely terrifying for security.</p>
<p>Because right now, for most companies, that &ldquo;frozen lasagna&rdquo; of software has no ingredients list. It has no seal of authenticity. We are effectively taking binary blobs from the internet (from strangers we have never met, using handles we don&rsquo;t recognize) and running them in the heart of our sovereign infrastructure. We are downloading packages from NPM, or PyPi, or Docker Hub, often without a second thought.</p>
<p>Consider the phenomenon of &ldquo;Typosquatting.&rdquo; An attacker notices that your developers use a popular python library called requests. So, the attacker uploads a malicious library called requessts (with an extra &ldquo;s&rdquo;) containing malware. One tired developer makes one typo in a configuration file, and suddenly, you have just invited a trojan horse into your production environment.</p>
<p>We have seen exactly what happens when this goes wrong. We all remember the absolute chaos of Log4j. It wasn&rsquo;t just a bug; it was a systemic failure. It was a tiny logging library, maintained by volunteers, buried five layers deep in the dependency tree of almost every enterprise Java application in the world. When the vulnerability broke, Chief Security Officers didn&rsquo;t even know if they were affected or not! They had to scan thousands of servers manually because they didn&rsquo;t have an inventory.</p>
<p>And let&rsquo;s not forget SolarWinds. That was a pivotal moment. The attackers realized they don&rsquo;t need to spend months trying to break into your firewall if they can just poison the water supply. They didn&rsquo;t attack the customers directly; they injected malicious code into the build system of the vendor. They compromised the factory so that every product leaving the assembly line was pre-infected.</p>
<p>The question we need to answer today is simple, but it is deeply uncomfortable for most IT leaders: Do you actually know what is running in your cluster right now?</p>
<p>Not what you think is running. Not what the architecture diagram says should be running. But what is actually there? And if you don&rsquo;t know the answer to that question, how can you claim your infrastructure is sovereign? How can you claim you are compliant with upcoming regulations like the EU Cyber Resilience Act, NIS2, or DORA? These regulations are no longer suggestions; they are mandates that will hold boards of directors personally accountable for the hygiene of their digital supply chain.</p>
<p>We need a better way. We need the digital equivalent of a nutrition label, and we need a tamper-proof seal for every single digital artifact we deploy.</p>
<h2 id="the-three-pillars">The Three Pillars</h2>
<p>So, how do we fix this? How do we secure this massive, complex supply chain without slowing our developers down to a crawl? We cannot ask them to manually audit every line of code in every library they use. That is humanly impossible. If we add too much friction, they will just find ways around it, and we end up with Shadow IT, which is even worse.</p>
<p>The solution lies in automation, built on three pillars that are redefining the industry, well known since the times of the Roman Empire: Transparentia, Identitas, et Claustra.</p>
<p>Or in English, Transparency, Identity, and Guardrails.</p>
<h3 id="transparency">Transparency</h3>
<p>The first pillar is Transparency. In the physical manufacturing world, every part has a serial number. If a specific airbag in a car is found to be defective, the manufacturer knows exactly which cars have it and where they are.</p>
<p>In software, we call this an SBOM…</p>
<p>…also known as a Software Bill of Materials.</p>
<p>This is your ingredients list. It is a machine-readable inventory (usually in formats like SPDX or CycloneDX) that lists every single library, every dependency, and every version number inside your application.</p>
<p>Using open source tools like Syft,…</p>
<p>…or enterprise platforms like Red Hat Trusted Profile Analyzer, we can generate this list automatically every time we build an app. It digs deep (not just listing the top-level libraries you installed, but the transitive dependencies, that is, the libraries that those libraries installed).</p>
<p>What does a SBOM look like? Here&rsquo;s a fragment of one, showing a dependency on a library available via Maven.</p>
<p>Why does this matter? Imagine the next &ldquo;Log4j&rdquo; hits tomorrow morning at 9:00 AM. In the old world, you would spend weeks scanning networks, waking up developers, and panicking. In the new world, you simply query your database of SBOMs. You ask: &ldquo;Show me every container running Log4j version 2.14.&rdquo; You get the answer in seconds. You know exactly where the risk is, and you can surgically remove it. That is the power of transparency.</p>
<h3 id="identity">Identity</h3>
<p>The second pillar is Identity.</p>
<p>Because knowing the ingredients is good, but knowing who cooked the meal is better. We need to cryptographically sign our code to prove its origin.</p>
<p>Now, I see some of you wincing. I know the history here. Traditionally, code signing has been a nightmare. It usually involves managing private GPG keys that sit on developer laptops.</p>
<p>This approach has two fatal flaws:</p>
<p>First, the &ldquo;Bus Factor&rdquo;: If the developer leaves the company, does the key go with them?</p>
<p>Second, Key Hygiene: People lose keys, they leak keys to GitHub by accident, or they just turn the verification off because it breaks their workflow.</p>
<p>You can see the issue here. There&rsquo;s even an engineer with a third leg in there and another with a third arm holding a diskette. Clearly, not very DevSecOps.</p>
<p>This is where the future is changing. We are seeing a revolution with a project called Sigstore…</p>
<p>…which powers the Red Hat Trusted Artifact Signer.</p>
<p>Sigstore does for code signing what &ldquo;Let&rsquo;s Encrypt&rdquo; did for HTTPS. It makes it free, easy, and automated. It uses a concept called keyless signing.</p>
<p>Think of it like a hotel key card. When you check into a hotel, you don&rsquo;t get a metal key that you keep forever. You get a plastic card that works for your room, for exactly three days. If you lose it after three days, it doesn&rsquo;t matter. It’s useless.</p>
<p>Here is how Sigstore works: Your developers don&rsquo;t generate permanent private keys anymore. Instead, they sign their code using their corporate identity (their Google, Microsoft, or Red Hat login) via OpenID Connect. They prove who they are, and the system issues a short-lived, ephemeral certificate that exists just long enough to sign the code (maybe just ten minutes) and then disappears.</p>
<p>This event is recorded in a tamper-proof transparency log called Rekor. It provides a public, verifiable record that says, &ldquo;Yes, this specific developer signed this specific piece of code at this specific time.&rdquo; It removes the burden of key management. It turns signing from a chore into an invisible automated step.</p>
<h3 id="guardrails">Guardrails</h3>
<p>The third pillar is Guardrails.</p>
<p>This is the &ldquo;Bouncer&rdquo; at the door. It doesn&rsquo;t matter if you have a perfect SBOM and a valid signature if nobody checks them before the application goes live. If the bouncer is asleep, the club isn&rsquo;t safe.</p>
<p>We need an admission controller in our Kubernetes clusters. We use tools like Red Hat Advanced Cluster Security (or ACS) which integrates deeply with Kubernetes admission contexts.</p>
<p>ACS acts as a policy engine. It sits at the API gate of your OpenShift cluster. When a deployment tries to enter, ACS stops it and asks for ID. It checks the signature. It parses the attestation.</p>
<p>It runs a logic check against your specific rules. For example:</p>
<p>Rule 1: &ldquo;Was this image built on a developer&rsquo;s laptop?&rdquo;</p>
<p>Deployment Denied.</p>
<p>Rule 2: &ldquo;Container signed with the key of another department?&rdquo;</p>
<p>Deployment Denied.</p>
<p>Rule 3: &ldquo;Was this image built and signed by our Trusted Pipeline?&rdquo;</p>
<p>Yes. Access Granted.</p>
<p>This is the fundamental shift in our security posture. We stop relying on hope. We stop relying on manual spreadsheets or quarterly audits. We start relying on cryptographic proof and automated policy enforcement.</p>
<p>We move from &ldquo;Trust but Verify&rdquo; to &ldquo;Verify, then Trust.&rdquo; We make the cluster itself smart enough to reject the bad stuff.</p>
<p>So, as a recap, remember the three pillars: Transparency, Identity, and Guardrails.</p>
<h2 id="the-architecture-of-the-factory-floor">The Architecture of the Factory Floor</h2>
<p>So how does this look like in real life?</p>
<p>Let’s visualize how this looks in a real production environment. I want you to think of this as a high-security, automated factory floor.</p>
<p>It starts with the Developer. They are writing code, perhaps using an IDE plugin, and they push their changes to Git. That is the last human interaction in the process. From this moment on, the robots take over to ensure consistency and security.</p>
<p>This git push triggers our factory engine: Red Hat OpenShift Pipelines, based on Tekton.</p>
<p>Tekton spins up a pod to handle the build. But it doesn&rsquo;t just compile the code. It acts as an observer, a notary, and a security guard all wrapped in one.</p>
<p>Verification: It runs unit tests to ensure functionality.</p>
<p>Scanning: It scans the code for known vulnerabilities using scanners like Clair or Roxctl. If it finds a &ldquo;Critical&rdquo; CVE, the line stops right there. The build fails. The developer gets feedback immediately, not three weeks later.</p>
<p>Documentation: It generates that SBOM, creating the &ldquo;Nutrition Label&rdquo; for the software.</p>
<p>Sealing: Finally, it uses the Trusted Artifact Signer to cryptographically sign the container image. It stamps the software with a digital seal that says: &ldquo;This software was built by this sanctioned pipeline, at this time, and it has not been altered since.&rdquo;</p>
<p>Once the image is signed and sealed, it moves to the warehouse. In our case, this is Red Hat Quay, an enterprise registry.</p>
<p>Quay isn&rsquo;t just a dumb storage bucket; it understands these signatures and attachments. It keeps the image and its &ldquo;paperwork&rdquo; (the SBOM and signatures) together.</p>
<p>Quay also performs &ldquo;Time Machine&rdquo; scanning. Just because an image was safe yesterday doesn&rsquo;t mean it&rsquo;s safe today. New vulnerabilities are discovered every hour. If Quay detects that a stored image has become vulnerable overnight, it can tag it as unsafe and prevent it from being pulled.</p>
<p>Now, we have a signed, sealed package sitting in the warehouse. How do we get it to the customers? We use GitOps.</p>
<p>We use OpenShift GitOps, based on the Argo CD project. Argo is the delivery truck. It monitors the warehouse. When it sees a new, valid image is available, or when the git configuration changes, it reaches out to pull that image into the production cluster.</p>
<p>Crucially, Argo CD also handles Drift Detection. If a cowboy administrator SSHs into a server and manually changes a configuration, Argo notices the difference between the &ldquo;desired state&rdquo; (Git) and the &ldquo;actual state&rdquo; (Cluster). It will automatically overwrite the manual change, healing the system back to its trusted state.</p>
<p>But remember the bouncer we talked about?</p>
<p>As Argo tries to apply this update to the cluster, the OpenShift API pauses. The admission controller steps in. It verifies the signature against the public transparency log. It confirms the &ldquo;Chain of Custody.&rdquo;</p>
<p>It asks: &ldquo;Did this come from our factory? Does the signature match the public key we trust?&rdquo;</p>
<p>Because the signature matches your organization&rsquo;s trust policy, the gate opens, and the workload starts.</p>
<p>Conversely, if a developer tries to bypass this process (if they try to manually use kubectl or oc to deploy an unsigned container from their laptop, or if a hacker compromises a credential and tries to inject a rogue container) the cluster will reject it immediately. The admission controller will see there is no signature, or the wrong signature, and it will block the request before the container even pulls.</p>
<p>This entire process happens in minutes. The developer didn&rsquo;t have to run a security scan manually. They didn&rsquo;t have to manage a private key. They didn&rsquo;t have to open a ticket for a security review. They just pushed code. The platform (the Golden Path) handled the sovereignty, the compliance, and the security automatically.</p>
<h2 id="conclusion">Conclusion</h2>
<p>We have talked a lot about technology today: Tekton, Sigstore, Argo CD, OpenShift. We&rsquo;ve looked at diagrams and command lines. But I want to leave you with a thought about Trust.</p>
<p>For a long time, we treated security as a gate. It was a hurdle that developers had to jump over.</p>
<p>It was the &ldquo;Department of No.&rdquo; And because it was hard, and because it slowed people down, smart people found ways around it. That is how supply chains get broken. That is how vulnerabilities slip in. When security fights against velocity, velocity usually wins, and security suffers.</p>
<p>The approach we discussed today, this &ldquo;Trusted Software Supply Chain&rdquo;, flips the script entirely. It makes the secure way the easiest way.</p>
<p>Through the Trusted Software Supply Chain, Red Hat provides a tool for each of the three pillars: Transparency through the Trusted Profile Analyzer; Identity, thanks to the Trusted Artifact Signer; and Guardrails, with the Advanced Cluster Security for Kubernetes.</p>
<p>By embedding these checks into the platform itself, by using Red Hat OpenShift and these open source standards to automate the &ldquo;boring&rdquo; parts of compliance, we grant our developers the freedom to move fast. We give them the confidence to innovate, because we know the guardrails are solid. We stop asking them to be security experts and start giving them tools that are secure by default.</p>
<p>Sovereignty isn&rsquo;t just about where your servers are physically located or which cloud provider you pay. Sovereignty is knowing, with mathematical certainty, exactly what software is running on those servers and exactly who put it there. It is about having total visibility and control over your digital assets.</p>
<p>So my challenge to you is this: Don&rsquo;t leave your infrastructure to chance. Don&rsquo;t rely on implicit trust. Build the factory. Sign your code. And take back control of your supply chain.</p>
<p>Thank you very much for your attention.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/IjO95cHLzNY?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<iframe class="speakerdeck-iframe" style="border: 0px; background: padding-box rgba(0, 0, 0, 0.1); margin: 0px; padding: 0px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.2) 0px 5px 40px; width: 100%; height: auto; aspect-ratio: 560 / 315;" frameborder="0" src="https://speakerdeck.com/player/ea7b80e23f654a3db7b401868d462974" title="What's in your Container? Securing the Software Supply Chain without Slowing Down" allowfullscreen="true" allow="web-share" data-ratio="1.7777777777777777"></iframe>
]]></content:encoded></item><item><title>Oktubre</title><link>https://akos.ma/blog/oktubre/</link><pubDate>Fri, 22 May 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/oktubre/</guid><description><![CDATA[ <p>Let me tell you the story of what was sounding in <a href="/blog/going-to-buenos-aires-here-to-help-you/">Buenos Aires</a>&rsquo; FM radios almost exactly 40 years ago.</p>]]></description><content:encoded><![CDATA[ <p>Let me tell you the story of what was sounding in <a href="/blog/going-to-buenos-aires-here-to-help-you/">Buenos Aires</a>&rsquo; FM radios almost exactly 40 years ago.</p>
<p><a href="https://en.wikipedia.org/wiki/Oktubre">&ldquo;Oktubre&rdquo;</a>, by &ldquo;Patricio Rey y los Redonditos de Ricota&rdquo; released in its entirety in October 1986, is widely considered to be one of the greatest albums of <a href="/blog/the-very-quick-and-sloppy-guide-to-argentine-rock/">Argentine rock</a> of all time. During that year they released various singles off the album, among them one called &ldquo;Ji Ji Ji&rdquo;, a song which has become the <a href="https://en.wikipedia.org/wiki/List_of_signature_songs">signature song</a> of the band in the decades that followed.</p>
<p class="shadow"><img src="oktubre.jpg" alt=""></p>
<p>As you can see on the cover, the band took some inspiration from the history and culture (that&rsquo;s Latin for &ldquo;clichés&rdquo;) of the <a href="https://en.wikipedia.org/wiki/Soviet_Union">USSR</a>, in the process even performing a horizontal symmetric transformation on the wrong letter; yes, I guess the illustrator didn&rsquo;t know (or gloriously ignored) that it should have been a &ldquo;Я&rdquo; (called &ldquo;Ya&rdquo;), appearing in a context where it actually doesn&rsquo;t make any sense whatsoever… so we got an inverted &ldquo;B&rdquo;… that doesn&rsquo;t exist in the Cyrillic alphabet.</p>
<p>To my Russian readers, you can stop facepalming now. The final results are worth it, I promise.</p>
<p>The whole album is a very personal interpretation of the times we were living in 1986; cold war, <a href="https://en.wikipedia.org/wiki/Chernobyl_disaster">Chernobyl</a>, communism, nuclear scare, and whatnot, as seen from a country on the literal antipodes of the USSR, that was barely emerging from decades of intermittent on-and-off dictatorships. To my ears, the album sounds sometimes menacing, sometimes nostalgic, often tough, mostly terribly naïve.</p>
<p><a href="https://www.youtube.com/watch?v=rQAm0OWeQZY">The album is freely available</a> in the official channel of the band (whose name can be roughly translated as &ldquo;Patricio Rey and the <a href="https://en.wikipedia.org/wiki/Ricotta">Ricotta</a> Bites&rdquo;). The video contains the full album in order, with the original lyrics in Spanish.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/rQAm0OWeQZY?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>Speaking about which, in case you&rsquo;re interested, the lyrics don&rsquo;t make much sense, not even in Spanish, and not only on this album; they have always been a weird thing with Los Redondos. It&rsquo;s like they privileged the sounds of the words to their actual meaning, and hence people think that they convey some satanic or prophetic message.</p>
<p>It remains a favorite album of mine. I was finishing primary school when I heard it for the first time. My parents both detested Argentine rock; for my mother it was all about depravation and drugs and violence (and she was right to a point). I now firmly believe it&rsquo;s a masterpiece of rock, regardless of country, language, inspiration, colors, or origin. It&rsquo;s rich, layered, poetic, enthralling, fun, and of course to me, it brings oh so many memories.</p>
<p>Personal favorite songs: &ldquo;Semen-Up&rdquo; (yes, it&rsquo;s a pun and the word means exactly the same in Spanish and in English), &ldquo;Motor Psico&rdquo;, and of course &ldquo;Ji Ji Ji&rdquo; which sends shivers down my spine.</p>
<p>The Redondos disbanded in the early 2000s, and the lead singer (known as <a href="https://en.wikipedia.org/wiki/Indio_Solari">&ldquo;El Indio Solari&rdquo;</a>) continued his career with another band named &ldquo;Los Fundamentalistas del Aire Acondicionado&rdquo; (aka &ldquo;The Air Conditioning Fundamentalists&rdquo;). They played songs from the Redondos, of course, and had their masterpieces too, like <a href="https://www.youtube.com/watch?v=srMSlbAhfRw">&ldquo;Beemedobleve&rdquo;</a> (2013). El Indio also had some incredible collaborations with other bands, including this anthem called <a href="https://www.youtube.com/watch?v=4KllIDumz3o">&ldquo;Angel de los Perdedores&rdquo;</a> (&ldquo;Loser&rsquo;s Angel&rdquo;, 1997), with the most amazing lyrics:</p>
<blockquote>
<p>The night shatters your glass, selling illusions <br>
leaving you scraps of dreams, in the corners <br>
But, baby, your laughter is the magic of rock ‘n’ roll <br>
I bear the mark of your stings tattooed on me. <br>
<br>
You healed all your wounds with rotten water <br>
you lied to the devil three times, selling him flowers <br>
and you carried the Loser&rsquo;s Angel on your shoulders.</p>
</blockquote>
<p>In 2017 the Fundamentalistas performed the biggest rock concert in the history of Argentina (and probably many other countries) in front of… 400'000 souls. They literally took over a whole city in the middle of the Pampas (called <a href="https://en.wikipedia.org/wiki/Olavarr%C3%ADa,_Argent">Olavarría</a>) for a day.</p>
<p><a href="https://www.youtube.com/watch?v=WkCHFCfmaLo">This video</a> is filmed from the <a href="https://www.openculture.com/2020/09/debbie-harry-demonstrates-the-punk-pogo-dance-for-a-u-s-audience-1978.html">pogo</a>. Don&rsquo;t watch if you are sensible to lights and shaking cameras. Do watch it if you want a good laugh. Fast-forward to <a href="https://youtu.be/WkCHFCfmaLo?t=170">minute 2:50</a> for the crowd singing the chorus of &ldquo;Ji Ji Ji&rdquo;. To say it&rsquo;s epic is the understatement of the decade.</p>
<p>You have no idea the cult following around El Indio Solari and the Redondos. He&rsquo;s a bit like our version of <a href="https://en.wikipedia.org/wiki/Hunter_S._Thompson">Hunter S. Thompson</a> in all possible ways. Sadly, Indio announced being hit with Parkinson shortly after that megaconcert, and lives since then in seclusion in an undisclosed location, only known to a few close friends.</p>
<p>The final lyrics of &ldquo;Ji Ji Ji&rdquo; in English can be roughly translated as follows… and I&rsquo;ll leave the interpretation to you.</p>
<blockquote>
<p>The final cut is really intriguing <br>
It’s actually really entertaining <br>
You’re walking through the dark crowd, caught off guard <br>
Bullying those who’ve loved you <br>
<br>
I didn’t dream it, yeah, eh-eh-eh <br>
He stood up straight and toasted to your luck <br>
I didn’t dream it, yeah, eh-eh-eh <br>
And he offered himself better than ever <br>
I didn’t dream it, yeah, eh-eh-eh <br>
You were running adrift <br>
I didn’t dream it, yeah, eh-eh-eh <br>
Blind eyes wide open <br>
Please don&rsquo;t look, and don&rsquo;t turn on the light <br>
The image has disfigured you, uh-oh, uh-oh, uh-oh, uh-oh <br>
<br>
See? <br>
There&rsquo;s Chernobyl, Chernobyl <br>
Chernobyl, Chernobyl <br>
Chernobyl, Chernobyl</p>
</blockquote>
<p>Speaking about El Indio Solari, here&rsquo;s a picture I took in April in Buenos Aires; it is a graffiti at the corner of San Martín avenue and Punta Arenas street, in the neighborhood of La Paternal, showing El Indio, Maradona, the FIFA World Cup trophy, the seal of the Peronist party, and the veterans of Malvinas/Falklands. All strong symbols of my birthplace.</p>
<p class="shadow"><img src="graffiti.jpg" alt=""></p>
]]></content:encoded></item><item><title>Typst</title><link>https://akos.ma/blog/typst/</link><pubDate>Fri, 15 May 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/typst/</guid><description> Three years ago I wrote about a workflow to generate PDF files out of my Markdown content, both on this website and on De Programmatica Ipsum. That first setup involved Pandoc and TeX, and it was a solution that worked well, but was unfortunately slow as hell, particularly given the amount of articles I have in both sites. A faster solution was badly needed.</description><content:encoded><![CDATA[ <p>Three years ago I wrote about a workflow to <a href="/blog/exporting-hugo-to-pdf/">generate PDF files</a> out of my Markdown content, both on this website and on <a href="https://deprogrammaticaipsum.com/">De Programmatica Ipsum</a>. That first setup involved Pandoc and TeX, and it was a solution that worked well, but was unfortunately slow as hell, particularly given the amount of articles I have in both sites. A faster solution was badly needed.</p>
<p>Looking for options I discovered that <a href="https://pandoc.org/typst-property-output.html">Pandoc supports Typst</a> since version <a href="https://pandoc.org/releases.html#pandoc-3.1.2-2023-03-26">3.1.2</a>, released in March 2023… but then I asked myself, what is <a href="https://typst.app/">Typst</a>? Well it turns out it&rsquo;s a new markup language coupled with a processor toolchain written in Rust; not just another one of those great <a href="https://deprogrammaticaipsum.com/the-great-rewriting-in-rust/">&ldquo;rewritings in Rust&rdquo;</a> but a new product, aiming at the same market than LaTeX but with all the speed of a Rust-built binary.</p>
<p>Typst provides all of the features I need, including syntax highlighting, math equation support, links as footnotes, and much more. So I gave it a shot, and with the help of <a href="https://cursor.com/">Cursor</a> I adapted the old LaTeX template used to generate PDF files into the one required by Typst, and I launched the generation of PDF files. The final templates are <em>very</em> readable I have to say, much more than the equivalent ones for LaTeX, that&rsquo;s for sure.</p>
<p>So what happened? Well, the results were nothing short of <strong>spectacular</strong>. On my personal 2022 ThinkPad X1 Carbon (running Fedora 44) the time for a full build of all the PDF files for De Programmatica Ipsum went from more than 2 hours to… a mere 15 minutes 😳 ! And not only that, but there are many more configuration options available, providing much finer control over the final output.</p>
<p>I also adapted the PDF generation toolchain for my websites, and you can see the final products, for example on <a href="conway-in-c89.pdf">this website</a> or on <a href="https://deprogrammaticaipsum.com/pdf/issue-091-entertainment.pdf">De Programmatica Ipsum</a>. For reference, find below the Typst template I use for the PDFs generated with the contents of this website at the time of this writing.</p>
<pre tabindex="0"><code>// Pandoc Typst template
// Compatible with current Typst and Pandoc template variables.

#let horizontalrule = line(start: (25%, 0%), end: (75%, 0%))

#show terms: it =&gt; {
  it.children
    .map(child =&gt; [
      #strong[#child.term]
      #block(inset: (left: 1.5em, top: -0.4em))[#child.description]
    ])
    .join()
}

#set table(inset: 6pt, stroke: none)

#let admonition(title: [], strokeColor: rgb(&#34;#1976D2&#34;), fillColor: rgb(&#34;#E7F1FB&#34;), titleColor: rgb(&#34;#0D47A1&#34;), body) = block(
  width: 100%,
  inset: (x: 10pt, y: 8pt),
  radius: 4pt,
  fill: fillColor,
  stroke: (left: (paint: strokeColor, thickness: 2.3pt)),
)[
  #set text(size: 0.88em, weight: &#34;bold&#34;, fill: titleColor)
  #title
  #parbreak()
  #v(0.2em)
  #set text(size: 1em, weight: &#34;regular&#34;, fill: black)
  #body
]

#show figure.where(kind: table): set figure.caption(position: $if(table-caption-position)$$table-caption-position$$else$top$endif$)
#show figure.where(kind: image): set figure.caption(position: $if(figure-caption-position)$$figure-caption-position$$else$bottom$endif$)

#let resolve-image-path = path =&gt; {
  if path.starts-with(&#34;/&#34;) or path.starts-with(&#34;http://&#34;) or path.starts-with(&#34;https://&#34;) {
    path
  } else {
    let rp = &#34;$resource-path$&#34;
    if rp == &#34;&#34; {
      path
    } else {
      rp + &#34;/&#34; + path
    }
  }
}

#let _image = image
#let image(path, ..args) = _image(resolve-image-path(path), ..args)

#let month-name = m =&gt; (
  if m == &#34;01&#34; { &#34;January&#34; }
  else if m == &#34;02&#34; { &#34;February&#34; }
  else if m == &#34;03&#34; { &#34;March&#34; }
  else if m == &#34;04&#34; { &#34;April&#34; }
  else if m == &#34;05&#34; { &#34;May&#34; }
  else if m == &#34;06&#34; { &#34;June&#34; }
  else if m == &#34;07&#34; { &#34;July&#34; }
  else if m == &#34;08&#34; { &#34;August&#34; }
  else if m == &#34;09&#34; { &#34;September&#34; }
  else if m == &#34;10&#34; { &#34;October&#34; }
  else if m == &#34;11&#34; { &#34;November&#34; }
  else if m == &#34;12&#34; { &#34;December&#34; }
  else { m }
)

#let ordinal = day =&gt; {
  let d = int(day)
  if calc.rem(d, 100) == 11 or calc.rem(d, 100) == 12 or calc.rem(d, 100) == 13 {
    [#d#(&#34;th&#34;)]
  } else if calc.rem(d, 10) == 1 {
    [#d#(&#34;st&#34;)]
  } else if calc.rem(d, 10) == 2 {
    [#d#(&#34;nd&#34;)]
  } else if calc.rem(d, 10) == 3 {
    [#d#(&#34;rd&#34;)]
  } else {
    [#d#(&#34;th&#34;)]
  }
}

#let format-commit-date = raw =&gt; {
  // Accept YYYY-MM-DD or ISO-like values and keep first 10 chars.
  let clean = if raw.len() &gt;= 10 { raw.slice(0, 10) } else { raw }
  let parts = clean.split(&#34;-&#34;)
  if parts.len() == 3 {
    [#month-name(parts.at(1)) #ordinal(parts.at(2)), #parts.at(0)]
  } else {
    [#raw]
  }
}

#set smartquote(enabled: true)

$for(header-includes)$
$header-includes$

$endfor$

#show link: it =&gt; [
  #it.body
  #footnote(it.dest)
]

#show: doc =&gt; {
  set document(
$if(title-meta)$
    title: [$title-meta$],
$elseif(title)$
    title: [$title$],
$endif$
$if(subject)$
    description: [$subject$],
$endif$
$if(author-meta)$
    author: [$author-meta$],
$endif$
$if(keywords)$
    keywords: ($for(keywords)$[$keywords$]$sep$,$endfor$),
$endif$
  )

  $if(lang)$
  set text(lang: &#34;$lang$&#34;)
  $endif$

  $if(mainfont)$
  set text(font: (&#34;$mainfont$&#34;,))
  $else$
  set text(font: (&#34;IBM Plex Sans&#34;,))
  $endif$

  $if(fontsize)$
  set text(size: $fontsize$)
  $endif$

  $if(monofont)$
  show raw: set text(font: (&#34;$monofont$&#34;,))
  $else$
  show raw: set text(font: (&#34;IBM Plex Mono&#34;,))
  $endif$

  set page(
    numbering: none,
    footer: context {
      let n = counter(page).get().first()
      if n &gt; 1 {
        align(center, counter(page).display($if(page-numbering)$&#34;$page-numbering$&#34;$else$&#34;1&#34;$endif$))
      }
    },
  $if(papersize)$
    paper: &#34;$papersize$&#34;,
  $endif$
  $if(margin)$
    margin: ($for(margin/pairs)$$margin.key$: $margin.value$,$endfor$),
  $else$
    // More balanced defaults for article PDFs.
    margin: (top: 2.6cm, bottom: 2.2cm, left: 2.2cm, right: 2.2cm),
  $endif$
  )

  doc
}

$for(include-before)$
$include-before$

$endfor$

$if(title)$
#align(center)[
  #set text(size: 1.55em, weight: &#34;bold&#34;)
  $title$
  $if(subtitle)$
  #v(0.25em)
  #parbreak()
  #set text(size: 1.08em, weight: &#34;regular&#34;)
  $subtitle$
  $endif$
  $if(date)$
  #v(0.15em)
  #parbreak()
  #set text(size: 0.50em, weight: &#34;regular&#34;)
  #format-commit-date(&#34;$date$&#34;)
  #v(0.45em)
  #parbreak()
  $endif$
]

$if(abstract)$
#parbreak()
#heading(level: 1)[Abstract]
$abstract$
$endif$
$endif$

$if(image)$
#figure(
  image(&#34;$resource-path$/$image$&#34;),
)
$endif$

$if(toc)$
#outline(
$if(toc-title)$
  title: [$toc-title$],
$else$
  title: auto,
$endif$
  depth: $toc-depth$,
)
$endif$

$if(lof)$
#outline(
  title: [List of Figures],
  target: figure.where(kind: image),
)
$endif$

$if(lot)$
#outline(
  title: [List of Tables],
  target: figure.where(kind: table),
)
$endif$

$body$

$if(citations)$
$if(csl)$
#set bibliography(style: &#34;$csl$&#34;)
$elseif(bibliographystyle)$
#set bibliography(style: &#34;$bibliographystyle$&#34;)
$endif$
$if(bibliography)$

#bibliography($for(bibliography)$&#34;$bibliography$&#34;$sep$,$endfor$)
$endif$
$endif$

$for(include-after)$

$include-after$
$endfor$
</code></pre><p>You can download an example output of this new PDF generation toolchain in the form of the file <a href="conway-in-c89.pdf">conway-in-c89.pdf</a>, extracted using the source of <a href="/blog/conway-in-c89/">the article with the same name</a>.</p>
<embed src="conway-in-c89.pdf" width="100%" height="900px" />
]]></content:encoded></item><item><title>eiPott</title><link>https://akos.ma/blog/eipott/</link><pubDate>Fri, 08 May 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/eipott/</guid><description> In this blog I&amp;rsquo;ve often mentioned the name of my late friend Bertrand Dufresne, who passed away 10 years ago this year. Despite all the good memories I have with him, I wanted to remember him through an object he offered me once.</description><content:encoded><![CDATA[ <p>In this blog I&rsquo;ve often mentioned the name of my late friend <a href="/search/?q=bertrand+dufresne">Bertrand Dufresne</a>, who passed away 10 years ago this year. Despite all the good memories I have with him, I wanted to remember him through an object he offered me once.</p>
<p>The eiPott was this short-lived thingy made by <a href="https://koziol-shop.de/en">Koziol</a> in 2010: a small, colorful plastic dish where you could eat a hard-boiled egg.</p>
<p><img src="eipott.jpg" alt=""></p>
<p>The name (and the very shape of the thing, really) comes from the German words &ldquo;Ei&rdquo; (meaning &ldquo;Egg&rdquo;) and &ldquo;Pott&rdquo; (meaning… &ldquo;pot&rdquo;). And needless to say, the name was a pun around the word &ldquo;iPod&rdquo;, whereby in German you would pronounce &ldquo;eiPott&rdquo; similarly.</p>
<p>Of course Apple did not appreciate the joke, as the <a href="https://web.archive.org/web/20100823070851/https://macobserver.com/tmo/article/nein_eipott_fuer_sie_german_court_backs_apple_copyright/">Mac Observer</a> and many other news outlets reported back in the day. It was far more than a simple &ldquo;cease-and-desist&rdquo; thing; Apple literally took the infringement to the courts, and a German judge sided with Steve Jobs on this one. The settlement involved some fines and everything.</p>
<p>I remember posting a message on Twitter (remember? Yeah, those were the days) about the eiPott, and then I got a call from Bertrand, and we were both laughing uncontrollably about the thing for a while. We both thought it was as brilliant as it was clumsy; he had a law degree, so he knew that playing such a game wasn&rsquo;t going to come for free. But he loved the pun, a lot.</p>
<p>And next thing I know, a few days later I received a package in the post; a Koziol eiPott, bought by Bertrand and delivered to my place. He was like this. I still have my eiPott, proudly displayed in my home office, and every time I see it I remember him.</p>
<p>I miss Bertrand. 2016 was really a terrible year. We lost so much.</p>
]]></content:encoded></item><item><title>Keychron Q3 Max</title><link>https://akos.ma/blog/keychron-q3-max/</link><pubDate>Fri, 01 May 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/keychron-q3-max/</guid><description> &lt;p>This year I decided to treat myself with a new keyboard, and I&amp;rsquo;ve chosen the Keychron Q3 Max; this post is a short summary of my impressions after a few weeks of use.&lt;/p></description><content:encoded><![CDATA[ <p>This year I decided to treat myself with a new keyboard, and I&rsquo;ve chosen the Keychron Q3 Max; this post is a short summary of my impressions after a few weeks of use.</p>
<p>To begin with, the mandatory TL;DR: <strong>I love it</strong>. There is no way to put it; this is by far the best keyboard I have ever owned, and I cannot believe I didn&rsquo;t get one earlier. Seriously good. Of course I got mine with the mandatory US (ANSI) layout, which you can see in the picture below.</p>
<p class="shadow"><img src="keychron_q3_max.jpg" alt=""></p>
<p>There are several things that I found outstanding in this keyboard. Foremost, the packaging is (let&rsquo;s be honest) sublime. Outside the Apple galaxy, where things are always beautifully packaged, few manufacturers try to stand out in packaging; Keychron is the exception, clearly.</p>
<p>Then the accessories: it comes bundled with all sorts of tools and with keycaps replacing the dreaded &ldquo;Windows&rdquo; key, which faithful readers know <a href="https://deprogrammaticaipsum.com/why-wait-for-the-best-when-i-could-have-you/">I loathe and despise vehemently</a>. Inside a little bag there&rsquo;s a classic macOS &ldquo;Command&rdquo; key and a much more appropriate &ldquo;Alt&rdquo; key, which, as you can see in the picture, is the one I ended up installing.</p>
<p>Then there&rsquo;s the configuration. To change various settings on your keyboard, you can use the <a href="https://launcher.keychron.com/">Keychron Launcher</a>, which, surprisingly enough, is a web application. At the time of this writing, it is only available on Chrome (or Chromium, as is my case) or other browsers using the same engine (Opera and Edge, most notably). Although apparently Firefox will soon gain access to the coveted <a href="https://caniuse.com/wf-serial">Web Serial API</a>, which would expand the availability of this application to our beloved browser as well. Crossing fingers.</p>
<p>Then comes the keyboard itself; I&rsquo;ve chosen a unit with brown switches, and I have to say, I love it. It has the tactile feedback of the blue switches I already knew (my good old <a href="https://www.daskeyboard.com/daskeyboard-4-ultimate/">Das Keyboard 4 Ultimate</a> I bought in 2015 had blue switches), but without the insane level of noise. Yes, maybe I&rsquo;m getting old, and I need a bit quieter environment around me. Who knows?</p>
<p>Also: it is heavy! Very dense, almost as heavy as my old Das Keyboard but with a smaller size, and the construction quality is seriously good.</p>
<p>Some key combinations that I had to look for in the documentation, leaving them here for future reference:</p>
<ul>
<li><code>Fn + B</code> to see the battery level (as a very nice LED animation below the number row; I love those kinds of small details)</li>
<li><code>Fn + W</code> to increase the brightness of the LEDs and <code>Fn + S</code> to bring it down. Although there are also dedicated function keys for that (<code>Fn + F6</code> and <code>Fn + F5</code>, respectively).</li>
</ul>
<p>I love the fact that this keyboard comes with arrow + utility keys (<code>Ins</code>, <code>Del</code>, <code>Home</code>, <code>End</code>, <code>Page Up</code>, and <code>Page Down</code>) located in the standard location of most keyboards, without fancy <code>Fn +</code> combinations to make them work properly (my previous keyboard before the Keychron was a <a href="https://www.logitech.com/en-us/shop/p/mx-keys-mini">Logitech MX Keys Mini</a>… and it was a bit too minimalist for my taste). It also has a very handy volume knob next to the <code>F12</code> key, and did I mention that all keys are completely programmable through the Launcher application?</p>
<p>TIP: Fun fact: on my Fedora system, the microphone key on the top-right corner of the screen, supposedly launching Cortana on Windows, instead opens up the calculator on my Fedora. Of course you can customize that, but I actually use the calculator quite a bit, believe it or not, so this was definitely a nice surprise.</p>
<p>As for the LEDs beneath the keys, I opted for the &ldquo;heatmap&rdquo; setting, where the most used keys are the ones getting the &ldquo;hotter&rdquo; colors. I found that quite cool, and it&rsquo;s a funny way to discover my typing patterns.</p>
<p>Now for the less fun part: I tried accessing the Keychron Launcher app from two different laptops, both running Fedora 43, and in the first (my Lenovo laptop provided by Red Hat), it worked out of the box; however, on my personal one (a Lenovo ThinkPad X1 Carbon Gen 10), I could not make it recognize my device, and I was getting an error message looking like this:</p>
<p class="shadow"><img src="error.jpg" alt=""></p>
<p>A little bit of Google-fu later, I found the solution in a <a href="https://gist.github.com/morkev/3f08cf45f38610565455bf48190b1b7e">GitHub Gist</a> showing a short Bash script that gets the trick done. Run the script as sudo, et voilà! My keyboard was properly recognized by the system.</p>
<p>So, conclusion: I love this keyboard; it is very comfortable, I can type at full speed, and I can write more and more text for this blog and <a href="https://deprogrammaticaipsum.com/">my magazine</a> every day. Highly recommended!</p>
]]></content:encoded></item><item><title>Bestseller Talk</title><link>https://akos.ma/blog/bestseller-talk/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/bestseller-talk/</guid><description><![CDATA[ <p>Ten years ago, almost to the day, I delivered what turned out to be the &ldquo;best-selling&rdquo; talk of all my <a href="/talks">conference speaking career</a>, with effects that I can feel to this day.</p>]]></description><content:encoded><![CDATA[ <p>Ten years ago, almost to the day, I delivered what turned out to be the &ldquo;best-selling&rdquo; talk of all my <a href="/talks">conference speaking career</a>, with effects that I can feel to this day.</p>
<p>I was invited by my friend (and community extraordinaire) <a href="https://www.linkedin.com/in/bontojr/">Junior &ldquo;Bonto&rdquo; Bontognali</a> to talk at the first edition of the <a href="https://web.archive.org/web/20160419182517/https://appbuilders.ch/">App Builders</a> conference, the first (and to my knowledge, to this day the only) 100% Swiss conference about mobile applications, with tracks for both iOS and Android developers.</p>
<p>I ended up speaking at the first four editions of App Builders, from 2016 to 2019. They took place all over Switzerland, from Zürich in 2016 to <a href="https://web.archive.org/web/20170320234144/https://www.appbuilders.ch/">Lausanne in 2017</a> (in the French-speaking area of Switzerland, also known as the &ldquo;Romandie&rdquo;), to finally the gorgeous town of Lugano in the Italian-speaking section of the country for the <a href="https://web.archive.org/web/20180401061152/https://appbuilders.ch/">2018</a> and <a href="https://web.archive.org/web/20190109161801/https://appbuilders.ch/">2019</a> events.</p>
<p>That first edition in Zürich was more than memorable, totally epic, and featured sessions and attendees among which many luminaries (many of whom I have the immense privilege of calling friends) were there, like <a href="https://www.linkedin.com/in/anastasiiavoitova/">Anastasiia Voitova</a>, <a href="https://web.archive.org/web/20160419182517/http://natashatherobot.com/">Natasha Murashev</a>, <a href="https://www.linkedin.com/in/vikramkriplaney/">Vikram Kriplaney</a>, <a href="https://www.linkedin.com/in/seviu/">Sebastian Vieira</a>, <a href="https://www.sicpers.info/">Graham Lee</a>, <a href="https://www.dimsumthinking.com/Info/">Daniel Steinberg</a>, <a href="https://www.smashingmagazine.com/author/vitaly-friedman/">Vitaly Friedman</a>, <a href="https://seriot.ch/">Nicolas Seriot</a>, <a href="https://podcasts.apple.com/us/podcast/the-ideveloper-podcast/id400664935">Steve &ldquo;Scotty&rdquo; Scott</a>, <a href="https://www.linkedin.com/in/elitalon/">Eliezer Talón</a>, <a href="https://www.swiftbysundell.com/">John Sundell</a>, <a href="https://orta.io/">Orta Therox</a>, <a href="https://underplot.com/">Marin Todorov</a>, and so many more. If you were active in the Swiss mobile app development community ten years ago, you know the names I just mentioned; they ring more than just a bell.</p>
<p>And thus I delivered the closing keynote on the first day of App Builders 2016, in a session titled <a href="/blog/being-a-developer-after-40/">&ldquo;Being A Developer After 40&rdquo;</a>.</p>
<p>For some unknown reason, this talk hit a chord in the audience (I&rsquo;m sure it was the <a href="https://en.wikipedia.org/wiki/Office_Assistant">Clippy</a> reference, no doubt about that). It was one of my favorite moments on stage, ever. I had a blast. And I got what I suppose can be called a standing ovation at the end.</p>
<p>I am not used to these things, clearly.</p>
<p>Bonto and his team (among whom were my friends <a href="https://www.linkedin.com/in/susanna-riccardi/">Susanna Riccardi</a> and <a href="https://www.linkedin.com/in/balestrapatrick/">Patrick Balestra</a>) recorded the talk and posted the video <a href="https://www.youtube.com/watch?v=GQx_beRMHVg">on YouTube</a> a few days later. But the same evening of that talk, I published my speech <a href="https://web.archive.org/web/20160624032538/https://medium.freecodecamp.com/being-a-developer-after-40-3c5dd112210c?gi=3e3cf75102f3">on Medium</a> and went to bed, exhausted and happy.</p>
<p>The following day, as the speakers were starting their sessions, Bonto approached me and, without saying a word, showed me the home page of Hacker News on his iPhone.</p>
<p>I was speechless.</p>
<p class="shadow"><img src="../being-a-developer-after-40/images/hn.jpg" alt=""></p>
<p>What followed cannot be described as anything else but pure madness.</p>
<p>My Twitter and LinkedIn follower count jumped by 150% on a single day, and I got flooded with messages and congratulations by people from all over the world. The video on YouTube went into the thousands of views, and my Medium.com article (which I agreed to include in the FreeCodeCamp community of that website for a while) cumulated hundreds of thousands of views overnight. The article was reprinted by a (now defunct) monthly publication called <a href="https://web.archive.org/web/20180528155146/https://hackerbits.com/adrian-kosmaczewski-june-2016/">&ldquo;Hacker Bits.&rdquo;</a> Even crazier, I had people voluntarily translating the articles to other languages, and thus came to life versions in <a href="https://web.archive.org/web/20160429122557/https://habrahabr.ru/post/282674/">Russian</a>, <a href="https://web.archive.org/web/20160706090102/http://m.logout.hu/cikk/fejlesztonek_lenni_40_felett/fejlesztonek_lenni_40_felett.html">Hungarian</a>, <a href="https://web.archive.org/web/20160529041552/http://blog.zvestov.cz/item/176">Czech</a>, <a href="https://web.archive.org/web/20180502232414/https://lfbittencourt.com/sendo-desenvolvedor-depois-dos-40-db274feb9445">Portuguese</a>, <a href="https://web.archive.org/web/20170827225100/https://virgool.io/@abbasmousavi/%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%E2%80%8C%D9%86%D9%88%DB%8C%D8%B3-%D8%A8%D9%88%D8%AF%D9%86-%D8%A8%D8%B9%D8%AF-%D8%A7%D8%B2-%DA%86%D9%87%D9%84-%D8%B3%D8%A7%D9%84%DA%AF%DB%8C-being-a-developer-after-40-hwgu50jp5ih9">Farsi</a>, <a href="https://web.archive.org/web/20180502232324/https://techmaster.vn/posts/33882/lap-trinh-vien-lon-tuoi">Vietnamese</a>, and <a href="https://web.archive.org/web/20210621155009/https://rolandleth.com/tech/blog/a-fi-programator-dupa-40-de-ani">Romanian</a>. And finally, I was asked to re-deliver that same talk in <a href="https://www.reenadsouza.com/anchor-reena-hosts-mobile-developer-summit-2016/">India</a> in September 2016 and then in <a href="https://mixitconf.org/2017/etre-developpeur-apres-40-ans">France</a> in April 2017.</p>
<p>I still have people (colleagues, conference attendees, etc.) come up to me to tell me spontaneously of how much they liked it. And I&rsquo;m amazed to hear that, just like the first day.</p>
<p>To say that I&rsquo;m still speechless as I write these words would be the understatement of the decade. In particular, I&rsquo;m so thankful to all the translators for the time they took to adapt my words into so many languages. I know it was a lot of work… because, well, it&rsquo;s a really long speech with almost 5000 words!</p>
<p>After App Builders, Bonto and his team came up with another gem of a conference: <a href="https://web.archive.org/web/20161102132308/https://www.theswiftalps.com/">The Swift Alps</a>, held in November 2016 in the gorgeous town of Crans-Montana (a place that, sadly, became known by a horrendous <a href="https://en.wikipedia.org/wiki/2026_Crans-Montana_bar_fire">tragedy</a> at the beginning of this year). I participated in the first two Swift Alps, but my (already visible at the time) <a href="/blog/what-objective-c-3.0-could-have-been/">lack of enthusiasm for Swift</a> led me to drop out from that event, starting from the third edition onwards.</p>
<p>The pandemic was too strong for App Builders and Swift Alps; their <a href="https://appbuilders.ch/">last editions</a> were (at the time of this writing) in 2022, and since then, nothing else has happened. It&rsquo;s sad; it was a sensational family of events organized by the sweetest team ever. Hopefully we can get it back up on its feet one day.</p>
<p>So, there you go: 10 years later, I&rsquo;m so thankful for this talk and its warm reception by the community. Thank you all.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/GQx_beRMHVg?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

]]></content:encoded></item><item><title>Learning A New Programming Language per Year in the Age of AI</title><link>https://akos.ma/blog/learning-a-new-programming-language-per-year-in-the-age-of-ai/</link><pubDate>Fri, 17 Apr 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/learning-a-new-programming-language-per-year-in-the-age-of-ai/</guid><description> People don&amp;rsquo;t really learn new programming languages every year anymore thanks to AI, so why do I stick with this activity? Call me old fashioned, but I still like to dive into a new programming language every year, no matter what, and thus here comes yet another update in my lifelong obsession to learn more and more programming languages.</description><content:encoded><![CDATA[ <p>People don&rsquo;t really learn new programming languages every year anymore thanks to AI, so why do I stick with this activity? Call me old fashioned, but I still like to dive into a new programming language every year, no matter what, and thus here comes <a href="/tags/lang-per-year/">yet another</a> update in my lifelong obsession to learn more and more programming languages.</p>
<p>The current list is the following; those languages that appear in the <a href="https://gitlab.com/akosma/Conway">Conway Game of Life</a> project appear in bold.</p>
<ul>
<li>1992: <strong>QBasic</strong></li>
<li>1993: <strong>Turbo Pascal</strong></li>
<li>1994: <strong>ANSI C</strong></li>
<li>1995: <strong>Delphi</strong></li>
<li>1996: <strong>JavaScript</strong>. Others: HTML</li>
<li>1997: <strong>Java</strong></li>
<li>1998: <strong>VBScript</strong>. Others: CSS</li>
<li>1999: Transact-SQL</li>
<li>2000: <strong>C#</strong>. Others: Prolog</li>
<li>2001: <strong>C++</strong></li>
<li>2002: <strong>PHP</strong>. Others: C#</li>
<li>2003: <strong>Objective-C</strong></li>
<li>2004: <strong>Visual Basic.NET</strong></li>
<li>2005: <strong>Ruby</strong></li>
<li>2006: LINQ. Others: <strong>C# 2.0</strong>, <strong>C++</strong></li>
<li>2007: Erlang</li>
<li>2008: <strong>Python</strong></li>
<li>2009: <strong>Go</strong></li>
<li>2010: <strong>Common Lisp</strong></li>
<li>2011: <strong>Haskell</strong></li>
<li>2012: <strong>Lua</strong></li>
<li>2013: <strong>C++  11</strong></li>
<li>2014: <strong>Scala</strong></li>
<li>2015: <strong>Swift</strong>. Others: <strong>C++  14</strong></li>
<li>2016: <strong>Kotlin</strong>. Others: <strong>Swift 3</strong>, <strong>Java 1.7</strong></li>
<li>2017: <strong>TypeScript</strong>. Others: 68K Assembler, <strong>PHP 7</strong>, awk</li>
<li>2018: <strong>F#</strong>. Others: <strong>C# 7</strong>, Elisp</li>
<li>2019: <strong>Go</strong>. Others: Scheme, Ballerina</li>
<li>2020: <strong>Smalltalk</strong>. Others: <strong>COBOL</strong>, <strong>Rexx</strong></li>
<li>2021: <strong>Rust</strong>. Others: R</li>
<li>2022: <strong>Dart</strong>. Others: Elixir, <strong>Crystal</strong>, <strong>Perl</strong>, <strong>D</strong></li>
<li>2023: <strong>Zig</strong>. Others: <strong>Minimal BASIC</strong>, <strong>Fortran</strong></li>
<li>2024: <strong>Bash</strong>, Vala, APL</li>
<li>2025: <strong>C23</strong>, <strong>C++23</strong></li>
<li>2026: <strong>Hare</strong></li>
</ul>
<p>NOTE: Yes; the list above is 35 lines long. I can&rsquo;t really believe it.</p>
<h2 id="hare">Hare</h2>
<p>So yes, this year I dived into <a href="https://harelang.org/">Hare</a>, another one of those programming languages that aim to become the &ldquo;next C&rdquo;, allowing developers to write fast lower-level code, without… well, writing C. (Insert shrug emoji here.)</p>
<p>Here go some notes I took while diving into the subject, hopefully they&rsquo;ll be useful to you too.</p>
<ul>
<li><a href="https://harelang.org/">Home page</a>.</li>
<li>Created by <a href="https://drewdevault.com/">Drew DeVault</a>
<ul>
<li><a href="https://drewdevault.com/2022/04/25/Announcing-Hare.html">Announcement</a> and <a href="https://harelang.org/blog/2022-04-25-announcing-hare/">another announcement</a>.</li>
</ul>
</li>
<li><a href="https://sr.ht/~sircmpwn/hare/">Source code</a>
<ul>
<li>Based on the <a href="https://c9x.me/compile/">QBE backend</a> which I didn&rsquo;t know about.</li>
</ul>
</li>
<li><a href="https://docs.harelang.org/">Standard library docs</a></li>
</ul>
<p>This language has been around since 2022, so there&rsquo;s already quite a few &ldquo;first impressions&rdquo; out there, that I recommend you read, too:</p>
<ul>
<li>Quite a long (1 hour 40 minutes!) <a href="https://www.youtube.com/watch?v=2E3E_Rh3mvw">recording of a streaming session</a> with an introduction to the language (published in 2024).</li>
<li><a href="https://dhole.github.io/post/hare_first_impressions/">First impressions by Dhole</a></li>
<li><a href="https://vfoley.xyz/hare/">More impressions</a></li>
<li>And some <a href="https://tilde.team/~kiedtl/blog/hare/">very early impressions (2021)</a> by Kiëd Llaentenn.</li>
</ul>
<p>Finally, if you would like to see some example code written in Hare, I found the following:</p>
<ul>
<li>There&rsquo;s a <a href="https://harebyexample.org/">&ldquo;Hare by Example&rdquo;</a> website.</li>
<li><a href="https://ares-os.org/">An operating system</a> built with it, because why not.</li>
</ul>
<p>In my own experiment, I literally gave <a href="/blog/vibe-coding-with-cursor/">Cursor</a> the whole <a href="https://gitlab.com/akosma/Conway/">Conway project</a> and asked it to translate it to Hare; and lo and behold, it succeeded, with just 3 iterations.</p>
<div class="highlight"><pre tabindex="0" style="color:#757575;background-color:#000;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-hare" data-lang="hare"><span style="display:flex;"><span><span style="color:#ec0000">export</span> <span style="color:#ec0000">fn</span> main() <span style="color:#5f5fff">void</span> <span style="color:#ec0000">=</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">let</span> w <span style="color:#ec0000">=</span> world_new(<span style="color:#008900">30</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">const</span> p1 <span style="color:#ec0000">=</span> blinker(coord { x <span style="color:#ec0000">=</span> <span style="color:#008900">0</span>, y <span style="color:#ec0000">=</span> <span style="color:#008900">1</span> });
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">const</span> p2 <span style="color:#ec0000">=</span> beacon(coord { x <span style="color:#ec0000">=</span> <span style="color:#008900">10</span>, y <span style="color:#ec0000">=</span> <span style="color:#008900">10</span> });
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">const</span> p3 <span style="color:#ec0000">=</span> glider(coord { x <span style="color:#ec0000">=</span> <span style="color:#008900">4</span>, y <span style="color:#ec0000">=</span> <span style="color:#008900">5</span> });
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">const</span> p4 <span style="color:#ec0000">=</span> block(coord { x <span style="color:#ec0000">=</span> <span style="color:#008900">1</span>, y <span style="color:#ec0000">=</span> <span style="color:#008900">10</span> });
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">const</span> p5 <span style="color:#ec0000">=</span> block(coord { x <span style="color:#ec0000">=</span> <span style="color:#008900">18</span>, y <span style="color:#ec0000">=</span> <span style="color:#008900">3</span> });
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">const</span> p6 <span style="color:#ec0000">=</span> tub(coord { x <span style="color:#ec0000">=</span> <span style="color:#008900">6</span>, y <span style="color:#ec0000">=</span> <span style="color:#008900">1</span> });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	seed(<span style="color:#ec0000">&amp;</span>w, p1[..]);
</span></span><span style="display:flex;"><span>	seed(<span style="color:#ec0000">&amp;</span>w, p2[..]);
</span></span><span style="display:flex;"><span>	seed(<span style="color:#ec0000">&amp;</span>w, p3[..]);
</span></span><span style="display:flex;"><span>	seed(<span style="color:#ec0000">&amp;</span>w, p4[..]);
</span></span><span style="display:flex;"><span>	seed(<span style="color:#ec0000">&amp;</span>w, p5[..]);
</span></span><span style="display:flex;"><span>	seed(<span style="color:#ec0000">&amp;</span>w, p6[..]);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">let</span> generation <span style="color:#ec0000">=</span> <span style="color:#008900">0</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#ec0000">for</span> (<span style="color:#ec0000">true</span>) {
</span></span><span style="display:flex;"><span>		generation <span style="color:#ec0000">+=</span> <span style="color:#008900">1</span>;
</span></span><span style="display:flex;"><span>		world_print(w, generation);
</span></span><span style="display:flex;"><span>		time<span style="color:#ec0000">::</span>sleep(<span style="color:#008900">500</span> <span style="color:#ec0000">*</span> time<span style="color:#ec0000">::</span>MILLISECOND);
</span></span><span style="display:flex;"><span>		w <span style="color:#ec0000">=</span> world_evolve(w);
</span></span><span style="display:flex;"><span>	};
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>IMPORTANT: Interestingly, of all the &ldquo;C successor&rdquo; languages (a select group where Rust and Zig appear as pioneers) Hare is the one that requires the least amount of code to reproduce this application, more or less the same as Java, Dart, or D, while Zig and Rust require slightly longer codebases (25% longer for Zig, 40% longer for Rust) for the same results.</p>
<p>All in all, I found Hare interesting; it is worth exploring it more in the future, although you might infer from the lack of enthusiasm in my writing that there wasn&rsquo;t really anything special that caught my attention. It&rsquo;s a commendable and interesting work for sure, but that&rsquo;s all. (And, yes, I do sometimes expect a bit too much from programming languages, most probably.)</p>
]]></content:encoded></item><item><title>Systems of Linear Equations</title><link>https://akos.ma/blog/systems-of-linear-equations/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/systems-of-linear-equations/</guid><description> A few weeks ago I told the story of the exams I passed to enter the &amp;ldquo;Bachillerato Bilingüe&amp;rdquo; class in my high school. Among all the things we had to learn for the exam there was the substitution algorithm to solve systems of linear equations, which I’m going to quickly show here.</description><content:encoded><![CDATA[ <p><a href="/blog/sohcahtoa/">A few weeks ago</a> I told the story of the exams I passed to enter the “Bachillerato Bilingüe” class in my high school. Among all the things we had to learn for the exam there was the elimination algorithm to solve systems of linear equations, which I’m going to quickly show here.</p>
$$
\begin{cases}
(1) \quad x + y + z = 6 \\
(2) \quad 2x - y + z = 3 \\
(3) \quad 3x + 2y - z = 4
\end{cases}
$$<p>We can solve this step by step as follows. First, eliminate $y$ adding $(1)$ and $(2)$ together:</p>
$$
(x + y + z) + (2x - y + z) = 6 + 3
$$$$
3x + 2z = 9 \quad \mathbf{(4)}
$$<p>Eliminate $y$ multiplying equation $(2)$ by $2$ and adding it to equation $(3)$:</p>
$$
2(2x - y + z) = 2(3) \implies 4x - 2y + 2z = 6
$$<p>Adding this to equation $(3)$ we get:</p>
$$
(4x - 2y + 2z) + (3x + 2y - z) = 6 + 4
$$$$
7x + z = 10 \quad \mathbf{(5)}
$$<p>Solve the $2 \times 2$ system for $x$ and $z$: from equation $(5)$, we can see that $z = 10 - 7x$. Substitute this into equation $(4)$:</p>
$$
3x + 2(10 - 7x) = 9
$$$$
3x + 20 - 14x = 9
$$$$
-11x = -11 \implies \mathbf{x = 1}
$$<p>Now, find $z$:</p>
$$
z = 10 - 7(1) \implies \mathbf{z = 3}
$$<p>Finally, find $y$ using equation 1:</p>
$$
1 + y + 3 = 6
$$$$
y + 4 = 6 \implies \mathbf{y = 2}
$$<p>And the final solution is:</p>
$$
\mathbf{(x, y, z) = (1, 2, 3)}
$$<p>Et voilà! This simple algorithm was one of my discoveries of 1989. Then came other methods, including substitution and matrices (aka <a href="https://en.wikipedia.org/wiki/Cramer%27s_rule">Cramer’s rule</a>), but traditional calculus (that is, derivatives and integrals) wasn&rsquo;t a part of the curriculum for the exam.</p>
]]></content:encoded></item><item><title>How To Connect Boatswain to OBS Studio</title><link>https://akos.ma/blog/how-to-connect-boatswain-to-obs-studio/</link><pubDate>Fri, 03 Apr 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/how-to-connect-boatswain-to-obs-studio/</guid><description><![CDATA[ <p>I&rsquo;ve recently got myself an <a href="https://www.elgato.com/us/en/p/stream-deck">Elgato Stream Deck</a>, and although it doesn&rsquo;t natively support Linux, there&rsquo;s a nice app called <a href="https://apps.gnome.org/Boatswain/">Boatswain</a> that does the trick (not to be confused with the OCI <a href="https://boatswain.io/">container monitoring app</a> of the same name).</p>]]></description><content:encoded><![CDATA[ <p>I&rsquo;ve recently got myself an <a href="https://www.elgato.com/us/en/p/stream-deck">Elgato Stream Deck</a>, and although it doesn&rsquo;t natively support Linux, there&rsquo;s a nice app called <a href="https://apps.gnome.org/Boatswain/">Boatswain</a> that does the trick (not to be confused with the OCI <a href="https://boatswain.io/">container monitoring app</a> of the same name).</p>
<p>I tried to connect Boatswain to my Flatpak-installed version of <a href="https://obsproject.com/">OBS Studio</a> (of which I&rsquo;ve already talked in a <a href="/blog/live-streaming/">previous article</a>) to simplify its use, and I discovered that the latest versions of OBS Studio use a WebSocket 5-based API, while unfortunately Boatswain only speaks the old OBS Studio API based on WebSocket 4.</p>
<p>The solution consists in installing an <a href="https://github.com/obsproject/obs-websocket/releases">older version</a> of the <a href="https://github.com/obsproject/obs-websocket/">obs-websocket</a> plugin, which thankfully in Flatpak is just a simple command away:</p>
<div class="highlight"><pre tabindex="0" style="color:#757575;background-color:#000;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ flatpak install com.obsproject.Studio.Plugin.WebSocket
</span></span></code></pre></div><p>Once this is done, just customize your buttons on Boatswain, adding as many OBS-related tasks as you&rsquo;d like (to start and stop recording or streaming, to switch scenes, or even to mute your audio input) and have fun!</p>
]]></content:encoded></item></channel></rss>