<?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, 10 Jul 2026 00:00:00 +0200</lastBuildDate><atom:link href="https://akos.ma/index.xml" rel="self" type="application/rss+xml"/><item><title>Tango</title><link>https://akos.ma/blog/tango/</link><pubDate>Fri, 10 Jul 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/tango/</guid><description><![CDATA[ <p>Ah, so you think I&rsquo;m going to talk about the dance called <a href="https://en.wikipedia.org/wiki/Tango">Tango</a>; but no, this time I&rsquo;m going to talk about an <a href="https://es.wikipedia.org/wiki/Tango_(%C3%A1lbum_de_Charly_Garc%C3%ADa_y_Pedro_Aznar)">album called &ldquo;Tango&rdquo;</a>, by those two towering figures of <a href="/blog/the-very-quick-and-sloppy-guide-to-argentine-rock/">Argentine rock</a>, namely <a href="https://en.wikipedia.org/wiki/Charly_Garc%C3%ADa">Charly García</a> and <a href="https://es.wikipedia.org/wiki/Pedro_Aznar">Pedro Aznar</a>.</p>]]></description><content:encoded><![CDATA[ <p>Ah, so you think I&rsquo;m going to talk about the dance called <a href="https://en.wikipedia.org/wiki/Tango">Tango</a>; but no, this time I&rsquo;m going to talk about an <a href="https://es.wikipedia.org/wiki/Tango_(%C3%A1lbum_de_Charly_Garc%C3%ADa_y_Pedro_Aznar)">album called &ldquo;Tango&rdquo;</a>, by those two towering figures of <a href="/blog/the-very-quick-and-sloppy-guide-to-argentine-rock/">Argentine rock</a>, namely <a href="https://en.wikipedia.org/wiki/Charly_Garc%C3%ADa">Charly García</a> and <a href="https://es.wikipedia.org/wiki/Pedro_Aznar">Pedro Aznar</a>.</p>
<p>Now, you&rsquo;re reading this and you&rsquo;re probably asking yourself, why? As <a href="https://en.wikipedia.org/wiki/Simon_Sinek">Simon Sinek</a> once said, <a href="https://en.wikipedia.org/wiki/Start_with_Why">start with why</a>: why, why, why does this guy always talk to us without talking to us. Why, why, why.</p>
<p>Well, I&rsquo;ll tell you why. Because I am talking to you. More precisely, <a href="https://www.youtube.com/watch?v=Z7AERldCALc">I&rsquo;m talking to your heart</a>, which is exactly the title of a song by our national hero Charly García, released in &ldquo;Tango&rdquo; on March 29th, 1986, that is, a bit over 40 years ago, and I&rsquo;ll leave it up to you to Google Translate the <a href="https://genius.com/Charly-garcia-y-pedro-aznar-hablando-a-tu-corazon-lyrics">lyrics</a>, which are sublime.</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/Z7AERldCALc?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>Oh yeah, it does sound 1980s, huh? Those synths. THOSE SYNTHESIZERS.</p>
<p>Charly, being the superstar he still is (regardless of his substance abuse) has had <a href="https://es.wikipedia.org/wiki/Hello!_MTV_Unplugged">his own MTV Unplugged</a> album in the 1990s, because it was such a tradition, and within that Unplugged album there&rsquo;s another song I deeply love, (originally released together in the same album &ldquo;Tango&rdquo;), and that other incredible song is called <a href="https://www.youtube.com/watch?v=Fy1WuMSC7Wg">&ldquo;Pasajera en Trance&rdquo;</a>, and here it goes again because reasons. It speaks of distance, flow, travel, and so many other things.</p>
<p>&ldquo;She dances on the sea&rdquo;, says Charly.</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/Fy1WuMSC7Wg?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>OK, here go the lyrics, because they are out-of-this-world. Enjoy.</p>
<blockquote>
<p>She’s about to board, <br>
maybe she’ll snag a seat on the deck. <br>
She’s about to take off, <br>
she’s leaving. <br>
She travels without paying, <br>
the old trick of walking in the shadows. <br>
She dances on the sea, <br>
she’s leaving. <br>
Passenger in a trance, <br>
passenger in perpetual transit. <br>
Passenger in a trance, <br>
passing through the right places. <br>
True love, <br>
is like sleeping and being awake. <br>
True love, <br>
is like living in an airport.</p>
</blockquote>
<p>As Charly says at the end, &ldquo;merci beaucoup&rdquo;.</p>
]]></content:encoded></item><item><title>NeXTClock</title><link>https://akos.ma/blog/nextclock/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/nextclock/</guid><description><![CDATA[ <p>So here is a new project on GitLab called <a href="https://gitlab.com/akosma/nextclock">NeXTClock</a>: a small browser-based recreation of a NeXTSTEP-style clock applet from the 1990s. This modern version renders a 64-unit clock face into a square <code>&lt;canvas&gt;</code> using JavaScript and <code>requestAnimationFrame()</code>, with optional scaling from 64 to 500 pixels, because, well, Java Applets <a href="/blog/java-applets-in-2023/">aren&rsquo;t really a thing anymore</a>.</p>]]></description><content:encoded><![CDATA[ <p>So here is a new project on GitLab called <a href="https://gitlab.com/akosma/nextclock">NeXTClock</a>: a small browser-based recreation of a NeXTSTEP-style clock applet from the 1990s. This modern version renders a 64-unit clock face into a square <code>&lt;canvas&gt;</code> using JavaScript and <code>requestAnimationFrame()</code>, with optional scaling from 64 to 500 pixels, because, well, Java Applets <a href="/blog/java-applets-in-2023/">aren&rsquo;t really a thing anymore</a>.</p>
<h2 id="background">Background</h2>
<p>The original source code of the Java applet came from the <a href="https://web.archive.org/web/19981207040305/http://the-labs.com/NeXTClock/">Internet Archive</a>. This original <code>NeXTClock</code> applet was written by <a href="https://renekmueller.com/">Rene K. Mueller</a> and is preserved in <code>original/NeXTClock.java</code> in the GitLab project. That applet used <a href="https://en.wikipedia.org/wiki/Abstract_Window_Toolkit">AWT</a>, a background GIF, and a thread that updated the displayed time. I used that Java applet in my <a href="/blog/gamma/">&ldquo;GaMMA&rdquo; home page</a> around 1999, until 2004.</p>
<p>Interestingly enough, the original Java version was written almost exactly 30 years ago at the time of this article:</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-java" data-lang="java"><span style="display:flex;"><span>// --- NeXTClock, written by Rene K. Mueller &lt;kiwi@the-labs.com&gt;
</span></span><span style="display:flex;"><span>//     V0.20: Jul 20, 1996
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> java.awt.Graphics;
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> java.awt.Image;
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> java.awt.Color;
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> java.awt.Font;
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> java.awt.FontMetrics;
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> java.util.Date;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">public</span> <span style="color:#ec0000">class</span> <span style="color:#5f5fff">NeXTClock</span> <span style="color:#ec0000">extends</span> java.<span style="color:#5f5fff">applet</span>.<span style="color:#5f5fff">Applet</span>
</span></span><span style="display:flex;"><span>        <span style="color:#ec0000">implements</span> Runnable {
</span></span><span style="display:flex;"><span>// ...
</span></span></code></pre></div><p>The translated source code in JavaScript in <code>src/NeXTClock.js</code> keeps the same 64 x 64 layout and the same visual idea: a NeXT-like clock tile with the weekday, day of the month, month, green seven-segment time, and blinking separator pixels. The drawing code scales that original layout to fit larger square canvases while preserving the pixelated look.</p>
<h2 id="usage">Usage</h2>
<p>Include <code>NeXTClock.js</code>, add a <code>&lt;CANVAS&gt;</code> object on your page, then create and start a clock:</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-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#ec0000">script</span> <span style="color:#5f5fff">src</span><span style="color:#ec0000">=</span><span style="color:#008900">&#34;NeXTClock.js&#34;</span>&gt;&lt;/<span style="color:#ec0000">script</span>&gt;
</span></span><span style="display:flex;"><span>&lt;<span style="color:#ec0000">canvas</span> <span style="color:#5f5fff">id</span><span style="color:#ec0000">=</span><span style="color:#008900">&#34;clock&#34;</span> <span style="color:#5f5fff">width</span><span style="color:#ec0000">=</span><span style="color:#008900">&#34;128&#34;</span> <span style="color:#5f5fff">height</span><span style="color:#ec0000">=</span><span style="color:#008900">&#34;128&#34;</span>&gt;&lt;/<span style="color:#ec0000">canvas</span>&gt;
</span></span><span style="display:flex;"><span>&lt;<span style="color:#ec0000">script</span>&gt;
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">const</span> canvas <span style="color:#ec0000">=</span> <span style="color:#ec0000">document</span>.getElementById(<span style="color:#008900">&#34;clock&#34;</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">const</span> clock <span style="color:#ec0000">=</span> <span style="color:#ec0000">new</span> NeXTClock(canvas, {
</span></span><span style="display:flex;"><span>    size<span style="color:#ec0000">:</span> <span style="color:#008900">128</span>,
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  clock.start();
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#ec0000">script</span>&gt;
</span></span></code></pre></div><p><noscript><img src="noscript.png" alt=""></noscript></p>
<p align="center">
<canvas id="clock1" width="64" height="64"></canvas>
&nbsp;
<canvas id="clock2" width="128" height="128"></canvas>
&nbsp;
<canvas id="clock3" width="256" height="256"></canvas>
</p>
<p style="text-align: center"><input type="button" id="startButton" value="Start"> <input type="button" id="stopButton" value="Stop"> <span id="timeSpan"></span><br>
<input type="range" min="0" max="1440" value="0" step="1" id="timeRange" style="width: 80%"></p>
<script src="NeXTClock.js"></script>
<script src="app.js"></script>
<p>The constructor expects an <code>HTMLCanvasElement</code>. By default, it uses the canvas display size and keeps it square. You can also pass a <code>size</code> option or call <code>setSize()</code> later; requested sizes are rounded and clamped between 64 and 500 pixels.</p>
<p>Available methods on the class:</p>
<ul>
<li><code>start()</code> begins animation using <code>requestAnimationFrame()</code>.</li>
<li><code>stop()</code> cancels the animation frame loop.</li>
<li><code>draw(date)</code> draws one frame for the supplied <code>Date</code>, or the current local time when omitted.</li>
<li><code>setSize(size)</code> updates the square canvas size and redraws the clock.</li>
</ul>
<p>You can pass the following options to the constructor:</p>
<ul>
<li><code>backgroundSrc</code>: optional path to a background image. When omitted, the built-in canvas background is used.</li>
<li><code>darkGreen</code>: color used for the seven-segment time display. Defaults to <code>#00c800</code>.</li>
<li><code>size</code>: optional square canvas size in pixels, clamped from 64 to 500.</li>
</ul>
<p>The clock automatically observes canvas resizing when <code>ResizeObserver</code> is available, so CSS-driven size changes are reflected in the next rendered frame.</p>
<p>As usual, you can grab the source code <a href="https://gitlab.com/akosma/nextclock">on my GitLab account</a>.</p>
]]></content:encoded></item><item><title>Goodbye, Cursor</title><link>https://akos.ma/blog/goodbye-cursor/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/goodbye-cursor/</guid><description><![CDATA[ <p>Regular readers of this blog know that <a href="/blog/vibe-coding-with-cursor/">I&rsquo;ve been</a> quite a happy user of <a href="https://cursor.com/">Cursor</a> for the past year, but the recent news of its mother company being <a href="https://www.cnbc.com/2026/06/16/spacex-spcx-cursor-acquisition-ipo.html">purchased</a> by SpaceX has made me reconsider my decision, and cancel my current subscription altogether.</p>]]></description><content:encoded><![CDATA[ <p>Regular readers of this blog know that <a href="/blog/vibe-coding-with-cursor/">I&rsquo;ve been</a> quite a happy user of <a href="https://cursor.com/">Cursor</a> for the past year, but the recent news of its mother company being <a href="https://www.cnbc.com/2026/06/16/spacex-spcx-cursor-acquisition-ipo.html">purchased</a> by SpaceX has made me reconsider my decision, and cancel my current subscription altogether.</p>
<p>The same way I don&rsquo;t have a Twitter account anymore, or I don&rsquo;t own (nor plan to buy) a Tesla, I prefer not to associate myself with certain billionaires out there. Personal choice.</p>
<p>There are several competitors of Cursor I&rsquo;ll be checking in the next few weeks for my personal use (the market of AI-enhanced coding tools is quite booming at the moment), among which I&rsquo;ll consider (in alphabetical order):</p>
<ul>
<li><a href="https://claude.com/product/claude-code">Anthropic Claude Code</a></li>
<li><a href="https://app.emergent.sh/landing/">Emergent</a></li>
<li><a href="https://antigravity.google/">Google Antigravity 2.0</a></li>
<li><a href="https://www.jetbrains.com/junie/">JetBrains Junie</a></li>
<li><a href="https://chatgpt.com/codex/">OpenAI Codex</a></li>
<li><a href="https://replit.com/">Replit</a></li>
</ul>
<p>And I&rsquo;ll give a second shot to <a href="https://github.com/features/copilot">GitHub Copilot</a>, which I had tried in early 2023 but without good results.</p>
]]></content:encoded></item><item><title>Conway in Haskell</title><link>https://akos.ma/blog/conway-in-haskell/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/conway-in-haskell/</guid><description><![CDATA[ <p>At this point it&rsquo;s becoming increasingly clear that I can ask <a href="https://cursor.com/">Cursor</a> to read any of the implementations of my <a href="https://gitlab.com/akosma/Conway/">Conway</a> and translate that into any other programming language that I want; this is what I&rsquo;ve done last year with <a href="/blog/conway-in-nasm/">NASM</a>, <a href="/blog/conway-in-scala/">Scala</a>, and <a href="/blog/conway-in-bash/">Bash</a>, and this year with Haskell.</p>]]></description><content:encoded><![CDATA[ <p>At this point it&rsquo;s becoming increasingly clear that I can ask <a href="https://cursor.com/">Cursor</a> to read any of the implementations of my <a href="https://gitlab.com/akosma/Conway/">Conway</a> and translate that into any other programming language that I want; this is what I&rsquo;ve done last year with <a href="/blog/conway-in-nasm/">NASM</a>, <a href="/blog/conway-in-scala/">Scala</a>, and <a href="/blog/conway-in-bash/">Bash</a>, and this year with Haskell.</p>
<p>Yes, I have read <a href="https://nostarch.com/lyah.htm">Miran Lipovača&rsquo;s masterpiece</a> but, like, <a href="/blog/learning-one-new-language-every-year/">15 years ago</a>, and to be honest I never quite got into using Haskell beyond small experiments. So what&rsquo;s a (lazy) developer to do in 2026? You guessed it. Particularly after writing a whole issue of De Programmatica Ipsum dedicated to the subject of <a href="https://deprogrammaticaipsum.com/issue/issue-093-functional-programming/">Functional Programming</a>, including an article about <a href="https://deprogrammaticaipsum.com/philip-wadler/">Philip Wadler</a>, one of the fathers of the language.</p>
<p>And once again, just like every time I use Cursor, I just let it do its thing after a good long prompt… and the magic operated in an uncanny way. The translation worked at first try, and I have nothing else to say at this point.</p>
<p>I do not know if you&rsquo;re fluent in Haskell, but this is the code I got at the end.</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-haskell" data-lang="haskell"><span style="display:flex;"><span><span style="color:#ec0000">#!/</span>usr<span style="color:#ec0000">/</span>bin<span style="color:#ec0000">/</span>env runghc
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> Conway.Coord (<span style="color:#5f5fff">Coord</span> (<span style="color:#ec0000">..</span>))
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> Conway.World (<span style="color:#5f5fff">World</span>, <span style="color:#5f5fff">beacon</span>, <span style="color:#5f5fff">blinker</span>, <span style="color:#5f5fff">block</span>, <span style="color:#5f5fff">evolve</span>, <span style="color:#5f5fff">glider</span>, <span style="color:#5f5fff">newWorld</span>, <span style="color:#5f5fff">tub</span>)
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> Control.Concurrent (<span style="color:#5f5fff">ThreadId</span>, <span style="color:#5f5fff">myThreadId</span>, <span style="color:#5f5fff">threadDelay</span>)
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> Control.Exception (<span style="color:#5f5fff">AsyncException</span> (<span style="color:#5f5fff">UserInterrupt</span>), <span style="color:#5f5fff">catch</span>, <span style="color:#5f5fff">throwIO</span>, <span style="color:#5f5fff">throwTo</span>)
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> System.Exit (<span style="color:#5f5fff">exitSuccess</span>)
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> System.Posix.Signals (<span style="color:#5f5fff">Handler</span> (<span style="color:#5f5fff">Catch</span>), <span style="color:#5f5fff">installHandler</span>, <span style="color:#5f5fff">sigINT</span>)
</span></span><span style="display:flex;"><span><span style="color:#ec0000">import</span> System.Process (<span style="color:#5f5fff">callCommand</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">clearScreen</span> <span style="color:#ec0000">::</span> <span style="color:#5f5fff">IO</span> <span style="color:#ec0000">()</span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">clearScreen</span> <span style="color:#ec0000">=</span> callCommand <span style="color:#008900">&#34;clear&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">handleSigInt</span> <span style="color:#ec0000">::</span> <span style="color:#5f5fff">ThreadId</span> <span style="color:#ec0000">-&gt;</span> <span style="color:#5f5fff">IO</span> <span style="color:#ec0000">()</span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">handleSigInt</span> mainThreadId <span style="color:#ec0000">=</span> throwTo mainThreadId <span style="color:#5f5fff">UserInterrupt</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">nextWorld</span> <span style="color:#ec0000">::</span> <span style="color:#5f5fff">Int</span> <span style="color:#ec0000">-&gt;</span> <span style="color:#5f5fff">World</span> <span style="color:#ec0000">-&gt;</span> <span style="color:#5f5fff">IO</span> <span style="color:#ec0000">()</span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">nextWorld</span> generation world <span style="color:#ec0000">=</span> <span style="color:#ec0000">do</span>
</span></span><span style="display:flex;"><span>  clearScreen
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">let</span> currentGeneration <span style="color:#ec0000">=</span> generation <span style="color:#ec0000">+</span> <span style="color:#008900">1</span>
</span></span><span style="display:flex;"><span>  putStr (show world)
</span></span><span style="display:flex;"><span>  putStrLn (<span style="color:#008900">&#34;Generation &#34;</span> <span style="color:#ec0000">++</span> show currentGeneration)
</span></span><span style="display:flex;"><span>  threadDelay <span style="color:#008900">500000</span>
</span></span><span style="display:flex;"><span>  nextWorld currentGeneration (evolve world)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">main</span> <span style="color:#ec0000">::</span> <span style="color:#5f5fff">IO</span> <span style="color:#ec0000">()</span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">main</span> <span style="color:#ec0000">=</span> <span style="color:#ec0000">do</span>
</span></span><span style="display:flex;"><span>  mainThreadId <span style="color:#ec0000">&lt;-</span> myThreadId
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">_</span> <span style="color:#ec0000">&lt;-</span> installHandler sigINT (<span style="color:#5f5fff">Catch</span> (handleSigInt mainThreadId)) <span style="color:#5f5fff">Nothing</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">let</span> aliveCells <span style="color:#ec0000">=</span>
</span></span><span style="display:flex;"><span>        blinker (<span style="color:#5f5fff">Coord</span> <span style="color:#008900">0</span> <span style="color:#008900">1</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ec0000">++</span> beacon (<span style="color:#5f5fff">Coord</span> <span style="color:#008900">10</span> <span style="color:#008900">10</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ec0000">++</span> glider (<span style="color:#5f5fff">Coord</span> <span style="color:#008900">4</span> <span style="color:#008900">5</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ec0000">++</span> block (<span style="color:#5f5fff">Coord</span> <span style="color:#008900">1</span> <span style="color:#008900">10</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ec0000">++</span> block (<span style="color:#5f5fff">Coord</span> <span style="color:#008900">18</span> <span style="color:#008900">3</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#ec0000">++</span> tub (<span style="color:#5f5fff">Coord</span> <span style="color:#008900">6</span> <span style="color:#008900">1</span>)
</span></span><span style="display:flex;"><span>      world <span style="color:#ec0000">=</span> newWorld <span style="color:#008900">30</span> aliveCells
</span></span><span style="display:flex;"><span>  nextWorld <span style="color:#008900">0</span> world `catch` handleUserInterrupt
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">handleUserInterrupt</span> <span style="color:#ec0000">::</span> <span style="color:#5f5fff">AsyncException</span> <span style="color:#ec0000">-&gt;</span> <span style="color:#5f5fff">IO</span> <span style="color:#ec0000">()</span>
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">handleUserInterrupt</span> <span style="color:#5f5fff">UserInterrupt</span> <span style="color:#ec0000">=</span> <span style="color:#ec0000">do</span>
</span></span><span style="display:flex;"><span>  clearScreen
</span></span><span style="display:flex;"><span>  exitSuccess
</span></span><span style="display:flex;"><span><span style="color:#5f5fff">handleUserInterrupt</span> exception <span style="color:#ec0000">=</span> throwIO exception
</span></span></code></pre></div><p>The final result shares quite a few similarities with F#; it&rsquo;s easy to see that there&rsquo;s a lot of inspiration from Haskell in F#, with the obvious exceptions of .NET-specific features like attributes and such.</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-fsharp" data-lang="fsharp"><span style="display:flex;"><span><span style="color:#ec0000">open</span> System
</span></span><span style="display:flex;"><span><span style="color:#ec0000">open</span> System.Threading
</span></span><span style="display:flex;"><span><span style="color:#ec0000">open</span> ConwayLib
</span></span><span style="display:flex;"><span><span style="color:#ec0000">open</span> Coord
</span></span><span style="display:flex;"><span><span style="color:#ec0000">open</span> World
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">[&lt;</span>EntryPoint<span style="color:#ec0000">&gt;]</span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">let</span> <span style="color:#ec0000">main</span> argv <span style="color:#ec0000">=</span>
</span></span><span style="display:flex;"><span>    Console.CancelKeyPress.Add <span style="color:#ec0000">(</span><span style="color:#ec0000">fun</span> arg <span style="color:#ec0000">-&gt;</span>
</span></span><span style="display:flex;"><span>        Console.Clear<span style="color:#ec0000">()</span>
</span></span><span style="display:flex;"><span>        Environment.Exit<span style="color:#ec0000">(</span>0<span style="color:#ec0000">))</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">let</span> <span style="color:#ec0000">blinker</span> <span style="color:#ec0000">=</span> blinker <span style="color:#ec0000">{</span> X <span style="color:#ec0000">=</span> 0<span style="color:#ec0000">;</span> Y <span style="color:#ec0000">=</span> 1 <span style="color:#ec0000">}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">let</span> <span style="color:#ec0000">beacon</span> <span style="color:#ec0000">=</span> beacon <span style="color:#ec0000">{</span> X <span style="color:#ec0000">=</span> 10<span style="color:#ec0000">;</span> Y <span style="color:#ec0000">=</span> 10 <span style="color:#ec0000">}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">let</span> <span style="color:#ec0000">glider</span> <span style="color:#ec0000">=</span> glider <span style="color:#ec0000">{</span> X <span style="color:#ec0000">=</span> 4<span style="color:#ec0000">;</span> Y <span style="color:#ec0000">=</span> 5 <span style="color:#ec0000">}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">let</span> <span style="color:#ec0000">block1</span> <span style="color:#ec0000">=</span> block <span style="color:#ec0000">{</span> X <span style="color:#ec0000">=</span> 1<span style="color:#ec0000">;</span> Y <span style="color:#ec0000">=</span> 10 <span style="color:#ec0000">}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">let</span> <span style="color:#ec0000">block2</span> <span style="color:#ec0000">=</span> block <span style="color:#ec0000">{</span> X <span style="color:#ec0000">=</span> 18<span style="color:#ec0000">;</span> Y <span style="color:#ec0000">=</span> 3 <span style="color:#ec0000">}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">let</span> <span style="color:#ec0000">tub</span> <span style="color:#ec0000">=</span> tub <span style="color:#ec0000">{</span> X <span style="color:#ec0000">=</span> 6<span style="color:#ec0000">;</span> Y <span style="color:#ec0000">=</span> 1 <span style="color:#ec0000">}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">let</span> <span style="color:#ec0000">aliveCells</span> <span style="color:#ec0000">=</span> blinker <span style="color:#ec0000">@</span> beacon <span style="color:#ec0000">@</span> glider <span style="color:#ec0000">@</span> block1 <span style="color:#ec0000">@</span> block2 <span style="color:#ec0000">@</span> tub
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">let</span> <span style="color:#ec0000">rec</span> iterate world generation <span style="color:#ec0000">=</span>
</span></span><span style="display:flex;"><span>        Console.Clear<span style="color:#ec0000">()</span>
</span></span><span style="display:flex;"><span>        printfn <span style="color:#008900">&#34;%s&#34;</span> <span style="color:#ec0000">(</span>worldDescription world<span style="color:#ec0000">)</span>
</span></span><span style="display:flex;"><span>        printfn <span style="color:#008900">&#34;Generation %d&#34;</span> <span style="color:#ec0000">(</span>generation<span style="color:#ec0000">)</span>
</span></span><span style="display:flex;"><span>        Thread.Sleep<span style="color:#ec0000">(</span>500<span style="color:#ec0000">)</span>
</span></span><span style="display:flex;"><span>        iterate <span style="color:#ec0000">(</span>evolve world<span style="color:#ec0000">)</span> <span style="color:#ec0000">(</span>generation <span style="color:#ec0000">+</span> 1<span style="color:#ec0000">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    iterate <span style="color:#ec0000">(</span>createWorld 30 aliveCells<span style="color:#ec0000">)</span> 1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    // return an integer exit code
</span></span><span style="display:flex;"><span>    0
</span></span></code></pre></div><p>This similarity is no coincidence. <a href="https://en.wikipedia.org/wiki/Don_Syme">Don Syme</a>, designer and architect of the F# programming language at Microsoft, acknowledged this legacy in his paper <a href="https://dl.acm.org/doi/10.1145/3386325">&ldquo;The early history of F#&rdquo;</a> submitted for HOPL IV in 2020.</p>
<blockquote>
<p>The history of the F# programming language is an arc drawn from the 1970s to the present day. Somewhere, back in the early 1970s, an idea was born in the mind of Robin Milner and his colleagues Lockwood Morris and Malcolm Newey of a succinct, fully type-inferred functional programming language suitable for manipulating structured information [Gordon 2000]. Building on the tradition of LISP (and indeed using LISP as their implementation vehicle), this language became ML Meta Language and is the root of a tradition of strongly typed functional programming languages that includes Edinburgh ML, Miranda, Haskell, Standard ML, OCaml, Elm, ReasonML and PureScript. F# is part of this family. <br>
(…) <br>
Initially, in late 2000, in conjunction with Reuben Thomas, I attempted an implementation of Haskell for .NET, using a direct translation from the Core intermediate representation of the Glasgow Haskell Compiler (GHC) to the .NET bytecode. This experience was partly successful: small programs ran. However, the advice of Simon Peyton Jones led me to believe that Haskell.NET couldn&rsquo;t be successful for several technical and cultural reasons: (…)</p>
</blockquote>
]]></content:encoded></item><item><title>Neovim</title><link>https://akos.ma/blog/neovim/</link><pubDate>Fri, 12 Jun 2026 00:00:00 +0200</pubDate><guid>https://akos.ma/blog/neovim/</guid><description><![CDATA[ <p>Call me late to the party if you want, but I recently adopted <a href="https://en.wikipedia.org/wiki/Neovim">Neovim</a> as my new full-time <a href="/blog/text-editors-for-work/">text editor for work</a>, and I have to say I&rsquo;m very pleased of having done so.</p>]]></description><content:encoded><![CDATA[ <p>Call me late to the party if you want, but I recently adopted <a href="https://en.wikipedia.org/wiki/Neovim">Neovim</a> as my new full-time <a href="/blog/text-editors-for-work/">text editor for work</a>, and I have to say I&rsquo;m very pleased of having done so.</p>
<p>In case you don&rsquo;t know (which given my audience, I&rsquo;d be surprised to hear) Neovim is a successor of Vim, built since 2014 on a fork of version 7 point something of Vim.</p>
<p>The good news is that it is almost 100% compatible with Vim, and that means I could reuse my good old <code>.vimrc</code>, using the following initialization file in <code>~/.config/nvim/init.vim</code></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-viml" data-lang="viml"><span style="display:flex;"><span><span style="color:#ec0000">set</span> runtimepath^=~<span style="color:#008900">/.vim runtimepath+=~/</span>.vim/after
</span></span><span style="display:flex;"><span><span style="color:#ec0000">let</span> &amp;packpath = &amp;runtimepath
</span></span><span style="display:flex;"><span>source ~/.vimrc
</span></span></code></pre></div><p>And that&rsquo;s it. The only line in my <code>.vimrc</code> that didn&rsquo;t work in Neovim was the following:</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-viml" data-lang="viml"><span style="display:flex;"><span><span style="color:#ec0000">set</span> guitablabel=%t
</span></span></code></pre></div><p>Which to be honest, I don&rsquo;t remember why it was there.</p>
<p>Most of the Vim plugins I had installed with Pathogen worked off-the-box, with the exception of Gundo, which had trouble accessing my Python environment; so I had to install a separate Python package for that:</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>$ pip3 install --user --upgrade pynvim
</span></span></code></pre></div><p>In my Fedora 44, I also installed the <code>neovim-qt</code> package, which provides a similar experience to Gvim on my desktop; this app uses its own configuration file, <code>~/.config/nvim/ginit.vim</code>, which in my case ended up looking like this:</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-viml" data-lang="viml"><span style="display:flex;"><span>&#34; Define your default font name and size
</span></span><span style="display:flex;"><span><span style="color:#ec0000">let</span> s:default_fontsize = <span style="color:#008900">15</span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">let</span> s:current_fontsize = s:default_fontsize
</span></span><span style="display:flex;"><span><span style="color:#ec0000">let</span> s:font_name = <span style="color:#008900">&#34;BlexMono Nerd Font&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">function</span>! AdjustFontSize(amount)
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">let</span> s:current_fontsize = s:current_fontsize + a:amount
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">execute</span> <span style="color:#008900">&#34;GuiFont! &#34;</span> . s:font_name . <span style="color:#008900">&#34;:h&#34;</span> . s:current_fontsize
</span></span><span style="display:flex;"><span><span style="color:#ec0000">endfunction</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">function</span>! ResetFontSize()
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">let</span> s:current_fontsize = s:default_fontsize
</span></span><span style="display:flex;"><span>  <span style="color:#ec0000">execute</span> <span style="color:#008900">&#34;GuiFont! &#34;</span> . s:font_name . <span style="color:#008900">&#34;:h&#34;</span> . s:current_fontsize
</span></span><span style="display:flex;"><span><span style="color:#ec0000">endfunction</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&#34; Mappings for Increasing Size (Ctrl + Plus / Ctrl + Equals)
</span></span><span style="display:flex;"><span>nnoremap &lt;C-+&gt; :call AdjustFontSize(<span style="color:#008900">1</span>)&lt;CR&gt;
</span></span><span style="display:flex;"><span>nnoremap &lt;C-=&gt; :call AdjustFontSize(<span style="color:#008900">1</span>)&lt;CR&gt;
</span></span><span style="display:flex;"><span>nnoremap &lt;C-kPlus&gt; :call AdjustFontSize(<span style="color:#008900">1</span>)&lt;CR&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&#34; Mappings for Decreasing Size (Ctrl + Minus)
</span></span><span style="display:flex;"><span>nnoremap &lt;C--&gt; :call AdjustFontSize(<span style="color:#008900">-1</span>)&lt;CR&gt;
</span></span><span style="display:flex;"><span>nnoremap &lt;C-kMinus&gt; :call AdjustFontSize(<span style="color:#008900">-1</span>)&lt;CR&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&#34; Mapping for Reset (Ctrl + Zero)
</span></span><span style="display:flex;"><span>nnoremap &lt;C<span style="color:#008900">-0</span>&gt; :call ResetFontSize()&lt;CR&gt;
</span></span><span style="display:flex;"><span>nnoremap &lt;C-k0&gt; :call ResetFontSize()&lt;CR&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&#34; Toggle Fullscreen with F11
</span></span><span style="display:flex;"><span><span style="color:#ec0000">let</span> s:my_fs_state = <span style="color:#008900">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">function</span>! ToggleFullScreen()
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">if</span> s:my_fs_state == <span style="color:#008900">0</span>
</span></span><span style="display:flex;"><span>        call GuiWindowFullScreen(<span style="color:#008900">1</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#ec0000">let</span> s:my_fs_state = <span style="color:#008900">1</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">else</span>
</span></span><span style="display:flex;"><span>        call GuiWindowFullScreen(<span style="color:#008900">0</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#ec0000">let</span> s:my_fs_state = <span style="color:#008900">0</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ec0000">endif</span>
</span></span><span style="display:flex;"><span><span style="color:#ec0000">endfunction</span>
</span></span><span style="display:flex;"><span>nnoremap &lt;silent&gt; &lt;F11&gt; :call ToggleFullScreen()&lt;CR&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&#34; Enable standard GUI clipboard shortcuts
</span></span><span style="display:flex;"><span>nnoremap &lt;C-S-v&gt; &#34;+p
</span></span><span style="display:flex;"><span>vnoremap &lt;C-S-v&gt; &#34;+p
</span></span><span style="display:flex;"><span>inoremap &lt;C-S-v&gt; &lt;C-r&gt;+
</span></span><span style="display:flex;"><span>cnoremap &lt;C-S-v&gt; &lt;C-r&gt;+
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>call ResetFontSize()
</span></span></code></pre></div><p>Neovim feels nice, snappy, fast, very convenient, and with a much more interesting roadmap ahead.</p>
<p><img src="neovim.png" alt=""></p>
]]></content:encoded></item><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>
<p><strong>Update, 2026-06-12:</strong> I&rsquo;m very sad to report that Carlos &ldquo;El Indio&rdquo; Solari passed away last Friday. He was 77 years old.</p>
<blockquote
    class="instagram-media"
    data-instgrm-captioned
    data-instgrm-permalink="https://www.instagram.com/p/DZOesIgN1DM"
    data-instgrm-version="14"
    style="
      background: #fff;
      border: 0;
      border-radius: 3px;
      box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5), 0 1px 10px 0 rgba(0, 0, 0, 0.15);
      margin: 1px;
      max-width: 540px;
      min-width: 326px;
      padding: 0;
      width: 99.375%;
      width: -webkit-calc(100% - 2px);
      width: calc(100% - 2px);
    "
  >
    <div style="padding: 16px">
      <a
        href="https://www.instagram.com/p/DZOesIgN1DM"
        style="
          background: #ffffff;
          line-height: 0;
          padding: 0 0;
          text-align: center;
          text-decoration: none;
          width: 100%;
        "
        target="_blank"
      >
        <div style="display: flex; flex-direction: row; align-items: center">
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 50%;
              flex-grow: 0;
              height: 40px;
              margin-right: 14px;
              width: 40px;
            "
          ></div>
          <div
            style="
              display: flex;
              flex-direction: column;
              flex-grow: 1;
              justify-content: center;
            "
          >
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 4px;
                flex-grow: 0;
                height: 14px;
                margin-bottom: 6px;
                width: 100px;
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 4px;
                flex-grow: 0;
                height: 14px;
                width: 60px;
              "
            ></div>
          </div>
        </div>
        <div style="padding: 19% 0"></div>
        <div
          style="display: block; height: 50px; margin: 0 auto 12px; width: 50px"
        >
          <svg
            width="50px"
            height="50px"
            viewBox="0 0 60 60"
            version="1.1"
            xmlns="https://www.w3.org/2000/svg"
            xmlns:xlink="https://www.w3.org/1999/xlink"
          >
            <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
              <g transform="translate(-511.000000, -20.000000)" fill="#000000">
                <g>
                  <path
                    d="M556.869,30.41 C554.814,30.41 553.148,32.076 553.148,34.131 C553.148,36.186 554.814,37.852 556.869,37.852 C558.924,37.852 560.59,36.186 560.59,34.131 C560.59,32.076 558.924,30.41 556.869,30.41 M541,60.657 C535.114,60.657 530.342,55.887 530.342,50 C530.342,44.114 535.114,39.342 541,39.342 C546.887,39.342 551.658,44.114 551.658,50 C551.658,55.887 546.887,60.657 541,60.657 M541,33.886 C532.1,33.886 524.886,41.1 524.886,50 C524.886,58.899 532.1,66.113 541,66.113 C549.9,66.113 557.115,58.899 557.115,50 C557.115,41.1 549.9,33.886 541,33.886 M565.378,62.101 C565.244,65.022 564.756,66.606 564.346,67.663 C563.803,69.06 563.154,70.057 562.106,71.106 C561.058,72.155 560.06,72.803 558.662,73.347 C557.607,73.757 556.021,74.244 553.102,74.378 C549.944,74.521 548.997,74.552 541,74.552 C533.003,74.552 532.056,74.521 528.898,74.378 C525.979,74.244 524.393,73.757 523.338,73.347 C521.94,72.803 520.942,72.155 519.894,71.106 C518.846,70.057 518.197,69.06 517.654,67.663 C517.244,66.606 516.755,65.022 516.623,62.101 C516.479,58.943 516.448,57.996 516.448,50 C516.448,42.003 516.479,41.056 516.623,37.899 C516.755,34.978 517.244,33.391 517.654,32.338 C518.197,30.938 518.846,29.942 519.894,28.894 C520.942,27.846 521.94,27.196 523.338,26.654 C524.393,26.244 525.979,25.756 528.898,25.623 C532.057,25.479 533.004,25.448 541,25.448 C548.997,25.448 549.943,25.479 553.102,25.623 C556.021,25.756 557.607,26.244 558.662,26.654 C560.06,27.196 561.058,27.846 562.106,28.894 C563.154,29.942 563.803,30.938 564.346,32.338 C564.756,33.391 565.244,34.978 565.378,37.899 C565.522,41.056 565.552,42.003 565.552,50 C565.552,57.996 565.522,58.943 565.378,62.101 M570.82,37.631 C570.674,34.438 570.167,32.258 569.425,30.349 C568.659,28.377 567.633,26.702 565.965,25.035 C564.297,23.368 562.623,22.342 560.652,21.575 C558.743,20.834 556.562,20.326 553.369,20.18 C550.169,20.033 549.148,20 541,20 C532.853,20 531.831,20.033 528.631,20.18 C525.438,20.326 523.257,20.834 521.349,21.575 C519.376,22.342 517.703,23.368 516.035,25.035 C514.368,26.702 513.342,28.377 512.574,30.349 C511.834,32.258 511.326,34.438 511.181,37.631 C511.035,40.831 511,41.851 511,50 C511,58.147 511.035,59.17 511.181,62.369 C511.326,65.562 511.834,67.743 512.574,69.651 C513.342,71.625 514.368,73.296 516.035,74.965 C517.703,76.634 519.376,77.658 521.349,78.425 C523.257,79.167 525.438,79.673 528.631,79.82 C531.831,79.965 532.853,80.001 541,80.001 C549.148,80.001 550.169,79.965 553.369,79.82 C556.562,79.673 558.743,79.167 560.652,78.425 C562.623,77.658 564.297,76.634 565.965,74.965 C567.633,73.296 568.659,71.625 569.425,69.651 C570.167,67.743 570.674,65.562 570.82,62.369 C570.966,59.17 571,58.147 571,50 C571,41.851 570.966,40.831 570.82,37.631"
                  ></path>
                </g>
              </g>
            </g>
          </svg>
        </div>
        <div style="padding-top: 8px">
          <div
            style="
              color: #3897f0;
              font-family: Arial, sans-serif;
              font-size: 14px;
              font-style: normal;
              font-weight: 550;
              line-height: 18px;
            "
          >
            View this post on Instagram
          </div>
        </div>
        <div style="padding: 12.5% 0"></div>
        <div
          style="
            display: flex;
            flex-direction: row;
            margin-bottom: 14px;
            align-items: center;
          "
        >
          <div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                height: 12.5px;
                width: 12.5px;
                transform: translateX(0px) translateY(7px);
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                height: 12.5px;
                transform: rotate(-45deg) translateX(3px) translateY(1px);
                width: 12.5px;
                flex-grow: 0;
                margin-right: 14px;
                margin-left: 2px;
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                height: 12.5px;
                width: 12.5px;
                transform: translateX(9px) translateY(-18px);
              "
            ></div>
          </div>
          <div style="margin-left: 8px">
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                flex-grow: 0;
                height: 20px;
                width: 20px;
              "
            ></div>
            <div
              style="
                width: 0;
                height: 0;
                border-top: 2px solid transparent;
                border-left: 6px solid #f4f4f4;
                border-bottom: 2px solid transparent;
                transform: translateX(16px) translateY(-4px) rotate(30deg);
              "
            ></div>
          </div>
          <div style="margin-left: auto">
            <div
              style="
                width: 0px;
                border-top: 8px solid #f4f4f4;
                border-right: 8px solid transparent;
                transform: translateY(16px);
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                flex-grow: 0;
                height: 12px;
                width: 16px;
                transform: translateY(-4px);
              "
            ></div>
            <div
              style="
                width: 0;
                height: 0;
                border-top: 8px solid #f4f4f4;
                border-left: 8px solid transparent;
                transform: translateY(-4px) translateX(8px);
              "
            ></div>
          </div>
        </div>
        <div
          style="
            display: flex;
            flex-direction: column;
            flex-grow: 1;
            justify-content: center;
            margin-bottom: 24px;
          "
        >
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 4px;
              flex-grow: 0;
              height: 14px;
              margin-bottom: 6px;
              width: 224px;
            "
          ></div>
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 4px;
              flex-grow: 0;
              height: 14px;
              width: 144px;
            "
          ></div></div
      ></a>
    </div>
  </blockquote><script async src="https://www.instagram.com/embed.js"></script>
<blockquote
    class="instagram-media"
    data-instgrm-captioned
    data-instgrm-permalink="https://www.instagram.com/p/DZNZ2u2Dp9i"
    data-instgrm-version="14"
    style="
      background: #fff;
      border: 0;
      border-radius: 3px;
      box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5), 0 1px 10px 0 rgba(0, 0, 0, 0.15);
      margin: 1px;
      max-width: 540px;
      min-width: 326px;
      padding: 0;
      width: 99.375%;
      width: -webkit-calc(100% - 2px);
      width: calc(100% - 2px);
    "
  >
    <div style="padding: 16px">
      <a
        href="https://www.instagram.com/p/DZNZ2u2Dp9i"
        style="
          background: #ffffff;
          line-height: 0;
          padding: 0 0;
          text-align: center;
          text-decoration: none;
          width: 100%;
        "
        target="_blank"
      >
        <div style="display: flex; flex-direction: row; align-items: center">
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 50%;
              flex-grow: 0;
              height: 40px;
              margin-right: 14px;
              width: 40px;
            "
          ></div>
          <div
            style="
              display: flex;
              flex-direction: column;
              flex-grow: 1;
              justify-content: center;
            "
          >
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 4px;
                flex-grow: 0;
                height: 14px;
                margin-bottom: 6px;
                width: 100px;
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 4px;
                flex-grow: 0;
                height: 14px;
                width: 60px;
              "
            ></div>
          </div>
        </div>
        <div style="padding: 19% 0"></div>
        <div
          style="display: block; height: 50px; margin: 0 auto 12px; width: 50px"
        >
          <svg
            width="50px"
            height="50px"
            viewBox="0 0 60 60"
            version="1.1"
            xmlns="https://www.w3.org/2000/svg"
            xmlns:xlink="https://www.w3.org/1999/xlink"
          >
            <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
              <g transform="translate(-511.000000, -20.000000)" fill="#000000">
                <g>
                  <path
                    d="M556.869,30.41 C554.814,30.41 553.148,32.076 553.148,34.131 C553.148,36.186 554.814,37.852 556.869,37.852 C558.924,37.852 560.59,36.186 560.59,34.131 C560.59,32.076 558.924,30.41 556.869,30.41 M541,60.657 C535.114,60.657 530.342,55.887 530.342,50 C530.342,44.114 535.114,39.342 541,39.342 C546.887,39.342 551.658,44.114 551.658,50 C551.658,55.887 546.887,60.657 541,60.657 M541,33.886 C532.1,33.886 524.886,41.1 524.886,50 C524.886,58.899 532.1,66.113 541,66.113 C549.9,66.113 557.115,58.899 557.115,50 C557.115,41.1 549.9,33.886 541,33.886 M565.378,62.101 C565.244,65.022 564.756,66.606 564.346,67.663 C563.803,69.06 563.154,70.057 562.106,71.106 C561.058,72.155 560.06,72.803 558.662,73.347 C557.607,73.757 556.021,74.244 553.102,74.378 C549.944,74.521 548.997,74.552 541,74.552 C533.003,74.552 532.056,74.521 528.898,74.378 C525.979,74.244 524.393,73.757 523.338,73.347 C521.94,72.803 520.942,72.155 519.894,71.106 C518.846,70.057 518.197,69.06 517.654,67.663 C517.244,66.606 516.755,65.022 516.623,62.101 C516.479,58.943 516.448,57.996 516.448,50 C516.448,42.003 516.479,41.056 516.623,37.899 C516.755,34.978 517.244,33.391 517.654,32.338 C518.197,30.938 518.846,29.942 519.894,28.894 C520.942,27.846 521.94,27.196 523.338,26.654 C524.393,26.244 525.979,25.756 528.898,25.623 C532.057,25.479 533.004,25.448 541,25.448 C548.997,25.448 549.943,25.479 553.102,25.623 C556.021,25.756 557.607,26.244 558.662,26.654 C560.06,27.196 561.058,27.846 562.106,28.894 C563.154,29.942 563.803,30.938 564.346,32.338 C564.756,33.391 565.244,34.978 565.378,37.899 C565.522,41.056 565.552,42.003 565.552,50 C565.552,57.996 565.522,58.943 565.378,62.101 M570.82,37.631 C570.674,34.438 570.167,32.258 569.425,30.349 C568.659,28.377 567.633,26.702 565.965,25.035 C564.297,23.368 562.623,22.342 560.652,21.575 C558.743,20.834 556.562,20.326 553.369,20.18 C550.169,20.033 549.148,20 541,20 C532.853,20 531.831,20.033 528.631,20.18 C525.438,20.326 523.257,20.834 521.349,21.575 C519.376,22.342 517.703,23.368 516.035,25.035 C514.368,26.702 513.342,28.377 512.574,30.349 C511.834,32.258 511.326,34.438 511.181,37.631 C511.035,40.831 511,41.851 511,50 C511,58.147 511.035,59.17 511.181,62.369 C511.326,65.562 511.834,67.743 512.574,69.651 C513.342,71.625 514.368,73.296 516.035,74.965 C517.703,76.634 519.376,77.658 521.349,78.425 C523.257,79.167 525.438,79.673 528.631,79.82 C531.831,79.965 532.853,80.001 541,80.001 C549.148,80.001 550.169,79.965 553.369,79.82 C556.562,79.673 558.743,79.167 560.652,78.425 C562.623,77.658 564.297,76.634 565.965,74.965 C567.633,73.296 568.659,71.625 569.425,69.651 C570.167,67.743 570.674,65.562 570.82,62.369 C570.966,59.17 571,58.147 571,50 C571,41.851 570.966,40.831 570.82,37.631"
                  ></path>
                </g>
              </g>
            </g>
          </svg>
        </div>
        <div style="padding-top: 8px">
          <div
            style="
              color: #3897f0;
              font-family: Arial, sans-serif;
              font-size: 14px;
              font-style: normal;
              font-weight: 550;
              line-height: 18px;
            "
          >
            View this post on Instagram
          </div>
        </div>
        <div style="padding: 12.5% 0"></div>
        <div
          style="
            display: flex;
            flex-direction: row;
            margin-bottom: 14px;
            align-items: center;
          "
        >
          <div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                height: 12.5px;
                width: 12.5px;
                transform: translateX(0px) translateY(7px);
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                height: 12.5px;
                transform: rotate(-45deg) translateX(3px) translateY(1px);
                width: 12.5px;
                flex-grow: 0;
                margin-right: 14px;
                margin-left: 2px;
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                height: 12.5px;
                width: 12.5px;
                transform: translateX(9px) translateY(-18px);
              "
            ></div>
          </div>
          <div style="margin-left: 8px">
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                flex-grow: 0;
                height: 20px;
                width: 20px;
              "
            ></div>
            <div
              style="
                width: 0;
                height: 0;
                border-top: 2px solid transparent;
                border-left: 6px solid #f4f4f4;
                border-bottom: 2px solid transparent;
                transform: translateX(16px) translateY(-4px) rotate(30deg);
              "
            ></div>
          </div>
          <div style="margin-left: auto">
            <div
              style="
                width: 0px;
                border-top: 8px solid #f4f4f4;
                border-right: 8px solid transparent;
                transform: translateY(16px);
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                flex-grow: 0;
                height: 12px;
                width: 16px;
                transform: translateY(-4px);
              "
            ></div>
            <div
              style="
                width: 0;
                height: 0;
                border-top: 8px solid #f4f4f4;
                border-left: 8px solid transparent;
                transform: translateY(-4px) translateX(8px);
              "
            ></div>
          </div>
        </div>
        <div
          style="
            display: flex;
            flex-direction: column;
            flex-grow: 1;
            justify-content: center;
            margin-bottom: 24px;
          "
        >
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 4px;
              flex-grow: 0;
              height: 14px;
              margin-bottom: 6px;
              width: 224px;
            "
          ></div>
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 4px;
              flex-grow: 0;
              height: 14px;
              width: 144px;
            "
          ></div></div
      ></a>
    </div>
  </blockquote><script async src="https://www.instagram.com/embed.js"></script>
<blockquote
    class="instagram-media"
    data-instgrm-captioned
    data-instgrm-permalink="https://www.instagram.com/p/DZN_RUnPmlY"
    data-instgrm-version="14"
    style="
      background: #fff;
      border: 0;
      border-radius: 3px;
      box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5), 0 1px 10px 0 rgba(0, 0, 0, 0.15);
      margin: 1px;
      max-width: 540px;
      min-width: 326px;
      padding: 0;
      width: 99.375%;
      width: -webkit-calc(100% - 2px);
      width: calc(100% - 2px);
    "
  >
    <div style="padding: 16px">
      <a
        href="https://www.instagram.com/p/DZN_RUnPmlY"
        style="
          background: #ffffff;
          line-height: 0;
          padding: 0 0;
          text-align: center;
          text-decoration: none;
          width: 100%;
        "
        target="_blank"
      >
        <div style="display: flex; flex-direction: row; align-items: center">
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 50%;
              flex-grow: 0;
              height: 40px;
              margin-right: 14px;
              width: 40px;
            "
          ></div>
          <div
            style="
              display: flex;
              flex-direction: column;
              flex-grow: 1;
              justify-content: center;
            "
          >
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 4px;
                flex-grow: 0;
                height: 14px;
                margin-bottom: 6px;
                width: 100px;
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 4px;
                flex-grow: 0;
                height: 14px;
                width: 60px;
              "
            ></div>
          </div>
        </div>
        <div style="padding: 19% 0"></div>
        <div
          style="display: block; height: 50px; margin: 0 auto 12px; width: 50px"
        >
          <svg
            width="50px"
            height="50px"
            viewBox="0 0 60 60"
            version="1.1"
            xmlns="https://www.w3.org/2000/svg"
            xmlns:xlink="https://www.w3.org/1999/xlink"
          >
            <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
              <g transform="translate(-511.000000, -20.000000)" fill="#000000">
                <g>
                  <path
                    d="M556.869,30.41 C554.814,30.41 553.148,32.076 553.148,34.131 C553.148,36.186 554.814,37.852 556.869,37.852 C558.924,37.852 560.59,36.186 560.59,34.131 C560.59,32.076 558.924,30.41 556.869,30.41 M541,60.657 C535.114,60.657 530.342,55.887 530.342,50 C530.342,44.114 535.114,39.342 541,39.342 C546.887,39.342 551.658,44.114 551.658,50 C551.658,55.887 546.887,60.657 541,60.657 M541,33.886 C532.1,33.886 524.886,41.1 524.886,50 C524.886,58.899 532.1,66.113 541,66.113 C549.9,66.113 557.115,58.899 557.115,50 C557.115,41.1 549.9,33.886 541,33.886 M565.378,62.101 C565.244,65.022 564.756,66.606 564.346,67.663 C563.803,69.06 563.154,70.057 562.106,71.106 C561.058,72.155 560.06,72.803 558.662,73.347 C557.607,73.757 556.021,74.244 553.102,74.378 C549.944,74.521 548.997,74.552 541,74.552 C533.003,74.552 532.056,74.521 528.898,74.378 C525.979,74.244 524.393,73.757 523.338,73.347 C521.94,72.803 520.942,72.155 519.894,71.106 C518.846,70.057 518.197,69.06 517.654,67.663 C517.244,66.606 516.755,65.022 516.623,62.101 C516.479,58.943 516.448,57.996 516.448,50 C516.448,42.003 516.479,41.056 516.623,37.899 C516.755,34.978 517.244,33.391 517.654,32.338 C518.197,30.938 518.846,29.942 519.894,28.894 C520.942,27.846 521.94,27.196 523.338,26.654 C524.393,26.244 525.979,25.756 528.898,25.623 C532.057,25.479 533.004,25.448 541,25.448 C548.997,25.448 549.943,25.479 553.102,25.623 C556.021,25.756 557.607,26.244 558.662,26.654 C560.06,27.196 561.058,27.846 562.106,28.894 C563.154,29.942 563.803,30.938 564.346,32.338 C564.756,33.391 565.244,34.978 565.378,37.899 C565.522,41.056 565.552,42.003 565.552,50 C565.552,57.996 565.522,58.943 565.378,62.101 M570.82,37.631 C570.674,34.438 570.167,32.258 569.425,30.349 C568.659,28.377 567.633,26.702 565.965,25.035 C564.297,23.368 562.623,22.342 560.652,21.575 C558.743,20.834 556.562,20.326 553.369,20.18 C550.169,20.033 549.148,20 541,20 C532.853,20 531.831,20.033 528.631,20.18 C525.438,20.326 523.257,20.834 521.349,21.575 C519.376,22.342 517.703,23.368 516.035,25.035 C514.368,26.702 513.342,28.377 512.574,30.349 C511.834,32.258 511.326,34.438 511.181,37.631 C511.035,40.831 511,41.851 511,50 C511,58.147 511.035,59.17 511.181,62.369 C511.326,65.562 511.834,67.743 512.574,69.651 C513.342,71.625 514.368,73.296 516.035,74.965 C517.703,76.634 519.376,77.658 521.349,78.425 C523.257,79.167 525.438,79.673 528.631,79.82 C531.831,79.965 532.853,80.001 541,80.001 C549.148,80.001 550.169,79.965 553.369,79.82 C556.562,79.673 558.743,79.167 560.652,78.425 C562.623,77.658 564.297,76.634 565.965,74.965 C567.633,73.296 568.659,71.625 569.425,69.651 C570.167,67.743 570.674,65.562 570.82,62.369 C570.966,59.17 571,58.147 571,50 C571,41.851 570.966,40.831 570.82,37.631"
                  ></path>
                </g>
              </g>
            </g>
          </svg>
        </div>
        <div style="padding-top: 8px">
          <div
            style="
              color: #3897f0;
              font-family: Arial, sans-serif;
              font-size: 14px;
              font-style: normal;
              font-weight: 550;
              line-height: 18px;
            "
          >
            View this post on Instagram
          </div>
        </div>
        <div style="padding: 12.5% 0"></div>
        <div
          style="
            display: flex;
            flex-direction: row;
            margin-bottom: 14px;
            align-items: center;
          "
        >
          <div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                height: 12.5px;
                width: 12.5px;
                transform: translateX(0px) translateY(7px);
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                height: 12.5px;
                transform: rotate(-45deg) translateX(3px) translateY(1px);
                width: 12.5px;
                flex-grow: 0;
                margin-right: 14px;
                margin-left: 2px;
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                height: 12.5px;
                width: 12.5px;
                transform: translateX(9px) translateY(-18px);
              "
            ></div>
          </div>
          <div style="margin-left: 8px">
            <div
              style="
                background-color: #f4f4f4;
                border-radius: 50%;
                flex-grow: 0;
                height: 20px;
                width: 20px;
              "
            ></div>
            <div
              style="
                width: 0;
                height: 0;
                border-top: 2px solid transparent;
                border-left: 6px solid #f4f4f4;
                border-bottom: 2px solid transparent;
                transform: translateX(16px) translateY(-4px) rotate(30deg);
              "
            ></div>
          </div>
          <div style="margin-left: auto">
            <div
              style="
                width: 0px;
                border-top: 8px solid #f4f4f4;
                border-right: 8px solid transparent;
                transform: translateY(16px);
              "
            ></div>
            <div
              style="
                background-color: #f4f4f4;
                flex-grow: 0;
                height: 12px;
                width: 16px;
                transform: translateY(-4px);
              "
            ></div>
            <div
              style="
                width: 0;
                height: 0;
                border-top: 8px solid #f4f4f4;
                border-left: 8px solid transparent;
                transform: translateY(-4px) translateX(8px);
              "
            ></div>
          </div>
        </div>
        <div
          style="
            display: flex;
            flex-direction: column;
            flex-grow: 1;
            justify-content: center;
            margin-bottom: 24px;
          "
        >
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 4px;
              flex-grow: 0;
              height: 14px;
              margin-bottom: 6px;
              width: 224px;
            "
          ></div>
          <div
            style="
              background-color: #f4f4f4;
              border-radius: 4px;
              flex-grow: 0;
              height: 14px;
              width: 144px;
            "
          ></div></div
      ></a>
    </div>
  </blockquote><script async src="https://www.instagram.com/embed.js"></script>
<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/UxfTDxxzjBE?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>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></channel></rss>