<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://www.yellowduck.be/pretty-atom-feed-v3.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <link href="https://www.yellowduck.be" rel="alternate"/>
  <link href="https://www.yellowduck.be/posts/feed" rel="self"/>
  <author>
    <name>Pieter Claerhout</name>
    <email>pieter@yellowduck.be</email>
  </author>
  <id>https://www.yellowduck.be/posts/feed</id>
  <title>🐥 YellowDuck.be</title>
  <updated>2026-06-09T17:00:00Z</updated>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/writing-code-that-feels-native-to-laravel" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Certain patterns emerge when working with Laravel that can greatly enhance your application code. The framework’s emphasis on convention over configuration creates a consistent experience; features integrate seamlessly due to familiar methods and behaviors.&lt;/p&gt;
&lt;p&gt;The article illustrates how Laravel&apos;s facades act as static proxies, resolving classes from the container, especially in testing environments. By adopting a similar approach in your own service classes, developers can enhance testability and promote consistency.&lt;/p&gt;
&lt;p&gt;This extends to defining methods like &lt;code&gt;handle&lt;/code&gt; for action classes, making them predictable and easy to work with.&lt;/p&gt;
&lt;p&gt;Ultimately, following Laravel&apos;s established conventions helps ensure that application code blends harmoniously with the framework, reducing complexity for future developers who interact with it.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://ryangjchandler.co.uk/posts/writing-code-that-feels-native-to-laravel&quot;&gt;Continue reading on &lt;strong&gt;ryangjchandler.co.uk&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/pattern&quot;&gt;#pattern&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/laravel&quot;&gt;#laravel&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/php&quot;&gt;#php&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/testing&quot;&gt;#testing&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-09T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/writing-code-that-feels-native-to-laravel</id>
    <title>🔗 Writing code that feels native to Laravel</title>
    <updated>2026-06-09T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-hidden-danger-of-shipping-fast" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Is it possible to ship too much – or too fast? Cleo highlights the risks that come with high product velocity, particularly when it surpasses user adoption. Many companies rush to deliver features, but this can result in a backlog of user unawareness and ultimately leads to reduced quality and increased time-to-value.&lt;/p&gt;
&lt;p&gt;Cleo emphasizes that the true bottleneck isn&apos;t the speed of production, but rather the limited user attention. Effective strategies include treating user attention as a scarce resource, building discovery directly within the product, and measuring learning outcomes, not just feature usage.&lt;/p&gt;
&lt;p&gt;Fast shipping can be beneficial, but only if it aligns with user adoption. Success lies in selective marketing and creating awareness that matches the pace of development.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://newsletter.posthog.com/p/the-hidden-danger-of-shipping-fast&quot;&gt;Continue reading on &lt;strong&gt;newsletter.posthog.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-09T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-hidden-danger-of-shipping-fast</id>
    <title>🔗 The hidden danger of shipping fast</title>
    <updated>2026-06-09T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/watching-for-file-changes-on-macos" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;When working on a website, live reload can greatly enhance productivity. This article outlines a method to implement this feature on macOS using the File System Events API. The author, who transitioned from using Jekyll to a custom static site generator, explains how to build a Swift script that listens for file system changes without relying on third-party libraries.&lt;/p&gt;
&lt;p&gt;The focus is on optimizing performance, with the final implementation detecting file changes within milliseconds, compared to slower polling methods. Step-by-step details, including handling cleanup and the event stream lifecycle, provide a comprehensive guide for developers looking to implement similar live reload capabilities in their projects. This approach not only showcases the technical implementation but also touches on practical performance considerations.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://alexwlchan.net/2026/watch-files-on-macos/&quot;&gt;Continue reading on &lt;strong&gt;alexwlchan.net&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/tools&quot;&gt;#tools&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/mac&quot;&gt;#mac&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-09T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/watching-for-file-changes-on-macos</id>
    <title>🔗 Watching for file changes on macOS</title>
    <updated>2026-06-09T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-silent-saboteur-how-quiet-can-break-your-laravel-command-sequences" rel="alternate"/>
    <content type="html">&lt;p&gt;When you chain multiple Artisan commands together in Laravel, there&apos;s a subtle trap waiting for you — one that&apos;s easy to miss because the commands still &lt;em&gt;run&lt;/em&gt;, they just stop &lt;em&gt;talking&lt;/em&gt;.&lt;/p&gt;
&lt;h1&gt;The setup&lt;/h1&gt;
&lt;p&gt;A common pattern in Laravel applications is a &quot;meta-command&quot; that runs a sequence of other commands in order. Think of a nightly job runner:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;keyword-modifier&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword-function&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;function&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;type-builtin&quot;&gt;int&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;lbrace;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;variable&quot;&gt;$commandsToRun&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;6&quot;&gt;        &lt;span class=&quot;type&quot;&gt;SomeCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;        &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;7&quot;&gt;        &lt;span class=&quot;type&quot;&gt;AnotherCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;     &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;8&quot;&gt;        &lt;span class=&quot;type&quot;&gt;DatabasePruneCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;--quiet&amp;#39;&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;9&quot;&gt;        &lt;span class=&quot;type&quot;&gt;MoreCommands&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;       &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;10&quot;&gt;        &lt;span class=&quot;type&quot;&gt;FinalCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;       &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;11&quot;&gt;    &lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;12&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;13&quot;&gt;    &lt;span class=&quot;keyword-repeat&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$commandsToRun&lt;/span&gt; &lt;span class=&quot;keyword-operator&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$commandToRun&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$parameters&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;lbrace;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;14&quot;&gt;        &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;variable-member&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$commandToRun&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;15&quot;&gt;        &lt;span class=&quot;type&quot;&gt;Artisan&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;function-call&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$commandToRun&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$parameters&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;variable-member&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;16&quot;&gt;    &lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;rbrace;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;17&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;18&quot;&gt;    &lt;span class=&quot;keyword-return&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable-builtin&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;SUCCESS&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;19&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;rbrace;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You pass &lt;code&gt;$this-&gt;output&lt;/code&gt; into each &lt;code&gt;Artisan::call&lt;/code&gt; so the sub-command&apos;s output flows through to the console. Clean and straightforward.&lt;/p&gt;
&lt;h1&gt;The problem&lt;/h1&gt;
&lt;p&gt;One of your commands — say, a prune command — is noisy by default. You don&apos;t want its output cluttering the logs, so you pass &lt;code&gt;&apos;--quiet&apos; =&gt; true&lt;/code&gt;. The title still appears, the command runs, everything looks fine.&lt;/p&gt;
&lt;p&gt;Then you notice something odd: the commands &lt;em&gt;after&lt;/em&gt; that quiet one stop printing their titles. The log files confirm they&apos;re running, but the console goes dark after that one &lt;code&gt;--quiet&lt;/code&gt; call.&lt;/p&gt;
&lt;h1&gt;Why it happens&lt;/h1&gt;
&lt;p&gt;When Laravel processes the &lt;code&gt;--quiet&lt;/code&gt; flag on a command, it calls:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;$output&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;setVerbosity&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;type&quot;&gt;OutputInterface&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;VERBOSITY_QUIET&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key word is &lt;strong&gt;on the output object you passed in&lt;/strong&gt;. Because you shared &lt;code&gt;$this-&gt;output&lt;/code&gt; across all &lt;code&gt;Artisan::call&lt;/code&gt; invocations, that single &lt;code&gt;setVerbosity&lt;/code&gt; call mutates the object in place. Every subsequent command — and every &lt;code&gt;title()&lt;/code&gt;, &lt;code&gt;info()&lt;/code&gt;, or &lt;code&gt;line()&lt;/code&gt; call — now runs against a quietly-configured output. They&apos;re suppressed silently, with no error.&lt;/p&gt;
&lt;p&gt;The commands still execute; they just can&apos;t speak.&lt;/p&gt;
&lt;h1&gt;The fix&lt;/h1&gt;
&lt;p&gt;Capture the verbosity before each call and restore it immediately after:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;keyword-repeat&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$commandsToRun&lt;/span&gt; &lt;span class=&quot;keyword-operator&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$commandToRun&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$parameters&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;lbrace;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;variable-member&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$commandToRun&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;6&quot;&gt;    &lt;span class=&quot;variable&quot;&gt;$verbosity&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;variable-member&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getVerbosity&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;7&quot;&gt;    &lt;span class=&quot;type&quot;&gt;Artisan&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;function-call&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$commandToRun&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$parameters&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;variable-member&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;8&quot;&gt;    &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;variable-member&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;setVerbosity&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$verbosity&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;9&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;rbrace;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two lines. The sub-command can do whatever it likes to the output during its run; your sequence always gets a clean slate for the next iteration.&lt;/p&gt;
&lt;h1&gt;The lesson&lt;/h1&gt;
&lt;p&gt;Shared mutable objects are the classic source of action-at-a-distance bugs. The output object here is a perfect example: you pass it in expecting read-like behaviour (writing to the terminal), but the callee has full write access to its configuration too.&lt;/p&gt;
&lt;p&gt;A few takeaways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Passing an object &quot;for output&quot; also grants mutation rights.&lt;/strong&gt; Laravel&apos;s &lt;code&gt;OutputStyle&lt;/code&gt; is stateful — verbosity, decorations, and more can be changed by anyone holding a reference.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Commands that still run aren&apos;t necessarily commands that are working correctly.&lt;/strong&gt; Silent output suppression looks identical to &quot;nothing went wrong&quot; if you&apos;re only checking exit codes or log files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test the observable side effects, not just execution.&lt;/strong&gt; A test that asserts &lt;code&gt;title()&lt;/code&gt; is called N times would have caught this immediately; a test that only checks &lt;code&gt;Artisan::call&lt;/code&gt; was invoked N times would not.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Bonus: write the test first&lt;/h1&gt;
&lt;p&gt;If you&apos;d written this test before the bug appeared, you&apos;d have been protected from day one:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;keyword-modifier&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword-function&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;function&quot;&gt;it_restores_verbosity_so_quiet_commands_do_not_suppress_subsequent_output&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;type-builtin&quot;&gt;void&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;lbrace;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Simulate a sub-command that sets quiet mode&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;6&quot;&gt;    &lt;span class=&quot;type&quot;&gt;Artisan&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;function-call&quot;&gt;shouldReceive&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;call&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;7&quot;&gt;        &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;twice&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;8&quot;&gt;        &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;andReturnUsing&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword-function&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;keyword-import&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$output&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;type-builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;lbrace;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;9&quot;&gt;            &lt;span class=&quot;variable&quot;&gt;$output&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;setVerbosity&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;type&quot;&gt;OutputInterface&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;VERBOSITY_QUIET&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;10&quot;&gt;            &lt;span class=&quot;keyword-return&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;11&quot;&gt;        &lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;rbrace;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;12&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;13&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Both titles must still appear&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;14&quot;&gt;    &lt;span class=&quot;variable&quot;&gt;$output&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;expects&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;exactly&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;title&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;15&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;16&quot;&gt;    &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;variable-member&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;runSequenceOfCommands&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;$command&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;17&quot;&gt;        &lt;span class=&quot;string&quot;&gt;&amp;#39;first:command&amp;#39;&lt;/span&gt;  &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;18&quot;&gt;        &lt;span class=&quot;string&quot;&gt;&amp;#39;second:command&amp;#39;&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;19&quot;&gt;    &lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;20&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;rbrace;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Shared mutable state is everywhere in framework code. A little defensive save-and-restore goes a long way.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/laravel&quot;&gt;#laravel&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-08T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-silent-saboteur-how-quiet-can-break-your-laravel-command-sequences</id>
    <title>🐥 The silent saboteur: how --quiet can break your Laravel command sequences</title>
    <updated>2026-06-08T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/chasing-a-phoenix-liveview-long-poll-reload-issue" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;The issue with the reload loop in a Phoenix 1.7 LiveView app stemmed from the requirement for long poll distribution. Users faced a frustrating loop where pages reloaded every seven seconds, showing a &quot;Something went wrong! Hang in there while we get back on track&quot; message. Despite staging environments working fine, the production setup running on AWS ECS behind Cloudflare illustrated a stark contrast due to server distribution.&lt;/p&gt;
&lt;p&gt;Debugging revealed a critical difference where production returned a &lt;code&gt;410&lt;/code&gt; status code related to session management—highlighting the necessity for all Phoenix nodes to connect for long poll fallback to function. Dan Schultzer meticulously details how enabling distribution resolved this issue and emphasizes the importance of this setup for ensuring proper PubSub messaging across all application nodes. A must-read for developers facing similar challenges in Phoenix apps.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://danschultzer.com/posts/chasing-phoenix-longpoll-reload-issue&quot;&gt;Continue reading on &lt;strong&gt;danschultzer.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/phoenix&quot;&gt;#phoenix&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-08T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/chasing-a-phoenix-liveview-long-poll-reload-issue</id>
    <title>🔗 Chasing a Phoenix LiveView long poll reload issue</title>
    <updated>2026-06-08T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/moving-away-from-tailwind-and-learning-to-structure-my-css" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Moving from Tailwind to a more semantic HTML and vanilla CSS approach can be liberating. The author reflects on their journey of migrating several sites away from Tailwind after years of reliance on it. They found newfound joy in structuring CSS and learned to impose systems that simplify the management of layouts, fonts, colors, and components. By adopting a component-based approach, reminiscent of modern frameworks, they established clearer boundaries in their styles.&lt;/p&gt;
&lt;p&gt;Emphasizing methodologies such as using CSS variables for colors and font sizes, they also explored responsive design through CSS Grid, minimizing the need for breakpoints. The motivations for this shift stem from a desire to embrace the depth of CSS while simultaneously moving away from Tailwind’s increasing dependency on build systems.&lt;/p&gt;
&lt;p&gt;This article highlights the author&apos;s evolving understanding of CSS and the excitement of rediscovered creativity in styling.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://jvns.ca/blog/2026/05/15/moving-away-from-tailwind--and-learning-to-structure-my-css-/&quot;&gt;Continue reading on &lt;strong&gt;jvns.ca&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/frontend&quot;&gt;#frontend&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/css&quot;&gt;#css&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-08T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/moving-away-from-tailwind-and-learning-to-structure-my-css</id>
    <title>🔗 Moving away from Tailwind, and learning to structure my CSS</title>
    <updated>2026-06-08T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/how-i-moved-my-digital-stack-to-europe" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;The urgency behind digital sovereignty often gets overlooked. However, this article provides a compelling case for why moving to European cloud services can not only provide better control over data but also align with personal values that prioritize privacy and autonomy.&lt;/p&gt;
&lt;p&gt;The author outlines their migration process, starting with the transition from Google Analytics to &lt;code&gt;Matomo&lt;/code&gt;, ensuring GDPR compliance without sacrificing functionality. Other shifts included moving from &lt;code&gt;Google Workspace&lt;/code&gt; to &lt;code&gt;Proton Mail&lt;/code&gt;, offering enhanced privacy protections, and switching from &lt;code&gt;AWS&lt;/code&gt; S3 to &lt;code&gt;Scaleway&lt;/code&gt; for more localized object storage.&lt;/p&gt;
&lt;p&gt;With each change, considerations for usability and long-term implications were meticulously documented, shedding light on the challenges and rewards of such a transformation.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://monokai.com/articles/how-i-moved-my-digital-stack-to-europe/&quot;&gt;Continue reading on &lt;strong&gt;monokai.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-07T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/how-i-moved-my-digital-stack-to-europe</id>
    <title>🔗 How I moved my digital stack to Europe</title>
    <updated>2026-06-07T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-myth-of-never-giving-up" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;There’s a myth in the startup world suggesting that relentless perseverance guarantees success. However, Marc Randolph challenges this notion by distinguishing between productive persistence and stubbornness. He argues that while persistence is vital, it’s crucial to recognize when efforts become futile. Randolph emphasizes two warning signs: when enthusiasm wanes and when all avenues have been exhausted without new insights.&lt;/p&gt;
&lt;p&gt;He shares a personal anecdote from his time at Netflix, illustrating how genuine curiosity can drive productive work. Ultimately, he stresses that every hour invested in a lost cause could hinder new opportunities. Balancing persistence and recognizing the right moments to pivot is pivotal for entrepreneurs. The key lies in being honest about one&apos;s enthusiasm and whether real learning and progress are occurring—allowing gut feelings to guide decisions.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://marcrandolph.substack.com/p/the-myth-of-never-giving-up&quot;&gt;Continue reading on &lt;strong&gt;marcrandolph.substack.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-07T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-myth-of-never-giving-up</id>
    <title>🔗 The myth of never giving up</title>
    <updated>2026-06-07T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/whats-gone-wrong-at-github" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Reliability issues are driving users away in their droves. GitHub’s uptime has plummeted, with 257 logged incidents in just a year. In a shocking turn, the rapid scaling of AI workflows overwhelmed the platform, leading to significant outages, notably in the CI/CD system, Actions. This instability has led prominent users, such as the maintainers of the Zig programming language and HashiCorp co-founder Mitchell Hashimoto, to migrate away, citing unreliability and a deteriorating engineering culture.&lt;/p&gt;
&lt;p&gt;GitHub’s CTO acknowledged that the platform wasn’t designed for the current scale demanded, and the integration of Copilot has only exacerbated the situation. As patience wanes among users, GitHub is now focused on ‘availability first’ in an attempt to regain trust amidst mounting pressure for better performance and reliability. The article raises critical questions about the future of GitHub and its role as a cornerstone of developer collaboration.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://leaddev.com/software-quality/whats-gone-wrong-at-github&quot;&gt;Continue reading on &lt;strong&gt;leaddev.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/github&quot;&gt;#github&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/announcement&quot;&gt;#announcement&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-07T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/whats-gone-wrong-at-github</id>
    <title>🔗 What’s gone wrong at GitHub?</title>
    <updated>2026-06-07T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/how-to-check-how-much-memory-a-systemd-unit-is-actually-using" rel="alternate"/>
    <content type="html">&lt;p&gt;When investigating memory usage on a Linux server, it&apos;s common to look at processes using tools such as &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;htop&lt;/code&gt;, or &lt;code&gt;ps&lt;/code&gt;. However, when applications are managed by systemd, it is often more useful to inspect memory usage at the service level rather than at the individual process level.&lt;/p&gt;
&lt;p&gt;This is especially important for services that spawn multiple worker processes.&lt;/p&gt;
&lt;h1&gt;Using systemctl&lt;/h1&gt;
&lt;p&gt;The easiest way to see the memory usage of a systemd unit is:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example output:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;Memory: 423.1M
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;CPU: 12min 34.567s
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This value represents the total memory usage of the service&apos;s cgroup, including all child processes managed by the unit.&lt;/p&gt;
&lt;h1&gt;Using systemctl show&lt;/h1&gt;
&lt;p&gt;For scripting and automation, use:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;--property=MemoryCurrent&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;MemoryCurrent=443662336
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The value is returned in bytes.&lt;/p&gt;
&lt;p&gt;To convert it to megabytes:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;--property=MemoryCurrent&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;--value&lt;/span&gt;&lt;span class=&quot;text&quot;&gt; \
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;function-call&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&amp;#39;&amp;lbrace; printf &quot;%.2f MB\n&quot;, $1 / 1024 / 1024 &amp;rbrace;&amp;#39;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Inspecting the cgroup directly&lt;/h1&gt;
&lt;p&gt;Systemd tracks resource usage through Linux cgroups.&lt;/p&gt;
&lt;p&gt;You can inspect the memory consumption directly:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;/sys/fs/cgroup/system.slice/my-service.service/memory.current&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or locate the cgroup first:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;--property=ControlGroup&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;ControlGroup=/system.slice/my-service.service
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then inspect the corresponding cgroup files.&lt;/p&gt;
&lt;h1&gt;Finding the processes behind a service&lt;/h1&gt;
&lt;p&gt;To see which processes belong to a unit:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;--property=MainPID&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can then inspect individual processes:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;ps&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;pid,rss,vsz,cmd&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;string-special-path&quot;&gt;PID&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keep in mind that summing RSS values from multiple processes can overestimate actual memory usage because shared memory pages may be counted multiple times.&lt;/p&gt;
&lt;h1&gt;Monitoring memory usage over time&lt;/h1&gt;
&lt;p&gt;For live monitoring:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;watch&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;text&quot;&gt; \
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;systemctl show my-service.service --property=MemoryCurrent --value&amp;#39;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or use:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemd-cgtop&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tool displays CPU, memory, and I/O usage per cgroup and is often the most convenient way to identify memory-hungry services on a system.&lt;/p&gt;
&lt;h1&gt;Configuring memory limits&lt;/h1&gt;
&lt;p&gt;Systemd can also enforce memory limits.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-ini&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;markup-heading&quot;&gt;Service&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;property&quot;&gt;MemoryMax&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;1G&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After updating the unit file:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;daemon-reload&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;restart&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To verify the configured limit:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;--property=MemoryMax&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;For services managed by systemd, &lt;code&gt;MemoryCurrent&lt;/code&gt; is usually the most accurate representation of how much memory the service is actually consuming. Unlike process-level tools, it accounts for the entire cgroup, making it ideal for monitoring applications that use worker pools, background jobs, or multiple child processes.&lt;/p&gt;
&lt;p&gt;Useful commands to remember:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemctl&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;my-service.service&lt;/span&gt; &lt;span class=&quot;variable-parameter&quot;&gt;--property=MemoryCurrent&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;function-call&quot;&gt;systemd-cgtop&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These provide a much clearer picture of service-level memory usage than inspecting individual processes alone.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/linux&quot;&gt;#linux&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sysadmin&quot;&gt;#sysadmin&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-06T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/how-to-check-how-much-memory-a-systemd-unit-is-actually-using</id>
    <title>🐥 How to check how much memory a systemd unit is actually using</title>
    <updated>2026-06-06T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;How does Claude Code thrive in the chaos of large codebases? In an article outlining best practices for deploying Claude Code at enterprise scale, the focus is on efficient navigation, effective harness setup, and contextual awareness. Claude Code manages codebases with millions of lines and varying architectures without needing a centralized index, directly accessing live code.&lt;/p&gt;
&lt;p&gt;It emphasizes the importance of contextual setup using CLAUDE.md files, which inform Claude’s operations. Efficient integration of hooks, skills, and plugins enhances its capabilities. This setup avoids common mistakes such as overloading context or failing to scope tools effectively. The detailed patterns and structures presented help organizations maximize Claude Code’s performance in their unique environments, ensuring cohesive and scalable workflows.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start&quot;&gt;Continue reading on &lt;strong&gt;claude.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-06T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start</id>
    <title>🔗 How Claude Code works in large codebases: Best practices and where to start</title>
    <updated>2026-06-06T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/what-if-the-browser-was-the-server" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;The article argues against the traditional SaaS model by suggesting that browsers could effectively serve as their own backends. It highlights how modern SaaS often merely acts as a middleman between users and databases, creating unnecessary delays through network communication.&lt;/p&gt;
&lt;p&gt;With advancements like WebAssembly (WASM) and the Origin Private File System (OPFS), developers can deploy fully functional backends that operate directly in users&apos; browsers. The article includes a proof of concept: a simple time tracker built using Go and SQLite, which utilizes OPFS for file storage.&lt;/p&gt;
&lt;p&gt;It emphasizes that this approach isn&apos;t suitable for applications requiring real-time collaboration, but it does open up new possibilities for many other applications that depend solely on personal data management. The concept could shift how software is distributed, challenging the prevailing assumption that all data must be stored on remote servers.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://arthurcornil.com/blog/ship-it-to-the-user/&quot;&gt;Continue reading on &lt;strong&gt;arthurcornil.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/golang&quot;&gt;#golang&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/frontend&quot;&gt;#frontend&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sqlite&quot;&gt;#sqlite&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-06T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/what-if-the-browser-was-the-server</id>
    <title>🔗 What if the browser was the server?</title>
    <updated>2026-06-06T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/using-daisyui-means-less-llm-cost-and-faster-ui-generation" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;If AI is writing the code, does it still matter if we use an efficient component library?&lt;/p&gt;
&lt;p&gt;daisyUI significantly reduces token costs and accelerates UI generation by streamlining code. By minimizing verbosity, daisyUI allows for just one class name instead of a long list of utility classes. This not only cuts down on the amount of code LLMs need to read and interpret but also speeds up development.&lt;/p&gt;
&lt;p&gt;For instance, a project using Tailwind + daisyUI generates approximately 79% less HTML compared to Tailwind alone, ultimately saving millions of tokens in AI workflows. These savings can dramatically affect project efficiency, making daisyUI a vital choice for developers relying on AI for UI creation.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://daisyui.com/blog/generate-ui-with-less-token/&quot;&gt;Continue reading on &lt;strong&gt;daisyui.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/frontend&quot;&gt;#frontend&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/css&quot;&gt;#css&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-05T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/using-daisyui-means-less-llm-cost-and-faster-ui-generation</id>
    <title>🔗 Using daisyUI means less LLM cost and faster UI generation</title>
    <updated>2026-06-05T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/34-days-in-an-elixir-tunnel-to-refactor-my-saas-without-a-rewrite" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Alzo, an Elixir SaaS for architecture firms, faced growth challenges due to its original architecture. Lucas Sifoni spent 34 days refactoring Alzo into a clustered multi-tenant application without a complete rewrite. He removed bottlenecks in the architecture, including eliminating the message broker, and adopted a new model where each tenant receives its own PostgreSQL schema&lt;/p&gt;
&lt;p&gt;This approach allowed for easier migrations and tenant management, although it introduced complexity in handling shared data. Sifoni utilized explicit scope passing for tenant data management and enlisted the aid of LLMs to handle numerous compilation errors. He updated the hot-code loading process to accommodate clustering and ensured the system remained efficient during upgrades.&lt;/p&gt;
&lt;p&gt;The effort proved worthwhile, enabling the company to grow without losing its iterative development advantages.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://lucassifoni.info/blog/34-days-of-refactoring&quot;&gt;Continue reading on &lt;strong&gt;lucassifoni.info&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/elixir&quot;&gt;#elixir&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/postgresql&quot;&gt;#postgresql&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-05T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/34-days-in-an-elixir-tunnel-to-refactor-my-saas-without-a-rewrite</id>
    <title>🔗 34 days in an Elixir tunnel to refactor my SaaS without a rewrite</title>
    <updated>2026-06-05T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/learnings-from-100k-lines-of-rust-with-ai" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;What can be achieved with 100,000 lines of Rust and AI? Cheng Huang shares insights from building a modern multi-Paxos consensus engine that outperforms Azure&apos;s original Replicated State Library. In just six weeks, he not only implemented all features of the library but also enhanced performance from 23,000 operations per second to 300,000.&lt;/p&gt;
&lt;p&gt;His workflow optimized AI coding agents like Claude Code and Codex, which played crucial roles in ensuring correctness through AI-driven code contracts and testing. Huang also redefined his development process with a lightweight spec-driven approach and aggressive performance optimization strategies, uncovering insights that dramatically improved throughput.&lt;/p&gt;
&lt;p&gt;With ambitions to further enhance AI-assisted coding, he believes that automating contract workflows and optimizing performance tuning could reshape the future of software development. This article unpacks the methodology and lessons learned, offering a glimpse into the potential of AI in programming.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://zfhuang99.github.io/rust/claude%20code/codex/contracts/spec-driven%20development/2025/12/01/rust-with-ai.html#wish-list-for-ai-assisted-coding&quot;&gt;Continue reading on &lt;strong&gt;zfhuang99.github.io&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/rust&quot;&gt;#rust&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/testing&quot;&gt;#testing&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-05T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/learnings-from-100k-lines-of-rust-with-ai</id>
    <title>🔗 Learnings from 100K lines of Rust with AI</title>
    <updated>2026-06-05T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/fixing-phpunit-13-with-without-expects-deprecations-in-laravel-tests" rel="alternate"/>
    <content type="html">&lt;p&gt;After upgrading to PHPUnit 13, you may run into this deprecation warning in Laravel test suites:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;Using with*() without expects() is deprecated and will no longer be possible in PHPUnit 14.
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first sight, the code often already looks correct:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;$mock&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;expects&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;once&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;runSequenceOfCommands&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;text&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what is actually causing the warning?&lt;/p&gt;
&lt;h1&gt;The real issue&lt;/h1&gt;
&lt;p&gt;In many Laravel applications, the problem comes from using Laravel’s &lt;code&gt;createPartialMock()&lt;/code&gt; helper together with newer PHPUnit versions.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;$class&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;createPartialMock&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;type&quot;&gt;NightlyCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;runSequenceOfCommands&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;6&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this worked fine in older PHPUnit versions, PHPUnit 13 tightened internal mock expectation handling and now emits deprecation warnings in some cases when using Laravel’s wrapper helpers.&lt;/p&gt;
&lt;h1&gt;The fix&lt;/h1&gt;
&lt;p&gt;Instead of &lt;code&gt;createPartialMock()&lt;/code&gt;, use PHPUnit’s native mock builder API.&lt;/p&gt;
&lt;p&gt;Replace this:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;$class&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;createPartialMock&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;type&quot;&gt;NightlyCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;runSequenceOfCommands&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;6&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;$class&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getMockBuilder&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;type&quot;&gt;NightlyCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;onlyMethods&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;runSequenceOfCommands&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getMock&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And for multiple mocked methods:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;$class&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getMockBuilder&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;type&quot;&gt;NightlyCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;onlyMethods&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;        &lt;span class=&quot;string&quot;&gt;&amp;#39;runSequenceOfCommands&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;6&quot;&gt;        &lt;span class=&quot;string&quot;&gt;&amp;#39;confirm&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;7&quot;&gt;    &lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;8&quot;&gt;    &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getMock&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Why this works&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;getMockBuilder()&lt;/code&gt; uses PHPUnit’s modern native mock API directly, avoiding the legacy compatibility layer behind Laravel’s partial mock helpers.&lt;/p&gt;
&lt;p&gt;This makes your tests:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;compatible with PHPUnit 13&lt;/li&gt;
&lt;li&gt;future-proof for PHPUnit 14&lt;/li&gt;
&lt;li&gt;less dependent on framework-specific mock wrappers&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Final result&lt;/h1&gt;
&lt;p&gt;Your expectations can stay exactly the same:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;expects&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;once&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;#39;runSequenceOfCommands&amp;#39;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;6&quot;&gt;        &lt;span class=&quot;variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;isInstanceOf&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;type&quot;&gt;NightlyCommand&lt;/span&gt;&lt;span class=&quot;operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;7&quot;&gt;        &lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;8&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// expected commands&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;9&quot;&gt;        &lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;10&quot;&gt;    &lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But by switching to &lt;code&gt;getMockBuilder()&lt;/code&gt;, the deprecation warning disappears cleanly.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/laravel&quot;&gt;#laravel&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/php&quot;&gt;#php&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/testing&quot;&gt;#testing&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-04T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/fixing-phpunit-13-with-without-expects-deprecations-in-laravel-tests</id>
    <title>🐥 Fixing PHPUnit 13 with*() without expects() deprecations in Laravel tests</title>
    <updated>2026-06-04T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/composable-sftp-streams-in-elixir" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;In Elixir, handling large media files over SFTP can lead to memory issues, especially with immense video files. Through lazy enumerables, Elixir allows developers to process streams efficiently without loading everything into memory. The article outlines how to use &lt;code&gt;File.stream!/2&lt;/code&gt; to manage this stream and demonstrates implementing the &lt;code&gt;Collectable&lt;/code&gt; protocol for custom SFTP streams. It emphasizes the architectural benefits of this approach, such as improved flexibility and adherence to Elixir conventions. By leveraging the &lt;code&gt;Stream.into/2&lt;/code&gt;, the implementation allows seamless integration and file transfers without overloading the process or complicating the existing codebase. This opens up avenues for better handling of file uploads to different destinations, like S3, while maintaining an elegant and functional programming style.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://kevinschweikert.de/posts/composable-sftp-streams/&quot;&gt;Continue reading on &lt;strong&gt;kevinschweikert.de&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/elixir&quot;&gt;#elixir&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-04T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/composable-sftp-streams-in-elixir</id>
    <title>🔗 Composable SFTP streams in Elixir</title>
    <updated>2026-06-04T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/how-i-write-http-clients" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;How do you build effective HTTP clients? Blain Smith shared his experiences developing HTTP clients for 3rd party APIs, outlining critical patterns he&apos;s observed. This includes essential components like composing client options, JSON encoding/decoding in Go, HTTP request signing, and creating convenience methods for easier API interactions.&lt;/p&gt;
&lt;p&gt;He highlights a practical example with the Infogram Go client, sharing code snippets for implementing struct tags and handling requests efficiently. Understanding these concepts can significantly boost the quality and testability of your HTTP clients. Smith&apos;s article serves as a valuable resource for developers looking to streamline their API interactions and improve their coding practices.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://blainsmith.com/articles/how-i-write-http-clients/&quot;&gt;Continue reading on &lt;strong&gt;blainsmith.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/golang&quot;&gt;#golang&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/pattern&quot;&gt;#pattern&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/http&quot;&gt;#http&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-04T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/how-i-write-http-clients</id>
    <title>🔗 How I write HTTP clients</title>
    <updated>2026-06-04T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/computer-use-is-45x-more-expensive-than-structured-apis" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;A benchmark study shows that AI agents using computer vision to navigate web interfaces are 45 times more expensive than those using structured APIs, largely due to higher token consumption and performance variance. While vision-based agents are still necessary for third-party software, auto-generating API surfaces for internal tools provides a far more efficient and cost-effective deployment strategy.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://reflex.dev/blog/computer-use-is-45x-more-expensive-than-structured-apis/&quot;&gt;Continue reading on &lt;strong&gt;reflex.dev&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/tools&quot;&gt;#tools&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-03T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/computer-use-is-45x-more-expensive-than-structured-apis</id>
    <title>🔗 Computer use is 45x more expensive than structured APIs</title>
    <updated>2026-06-03T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/why-developers-should-and-shouldnt-use-llms-in-our-development" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Why should I use AI? This pressing question is at the forefront of our evolving software development landscape. In the wake of LLMs like ChatGPT, developers must decide how to harness this technology effectively. While LLMs excel at handling repetitive tasks or producing prototypes quickly, they can compound security risks and tech debt if misused. I found that the clients I work with sometimes desire AI solutions even when they&apos;re unnecessary. This muddles our understanding of their actual needs, highlighting the importance of expert insight over flashy trends. I’ve noticed the most significant shifts in our workflow center on using LLMs to free developers from rote tasks, allowing us to focus on creative problem-solving instead. However, caution can&apos;t be overlooked: without proper review, LLM-generated code can lead to serious vulnerabilities.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://tighten.com/insights/pragmatic-ai-why-devs-should-and-shouldnt-use-llms/&quot;&gt;Continue reading on &lt;strong&gt;tighten.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-03T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/why-developers-should-and-shouldnt-use-llms-in-our-development</id>
    <title>🔗 Why developers should – and shouldn’t – use LLMs in our development</title>
    <updated>2026-06-03T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-robots-are-replacing-the-packages" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;The way AI-assisted development is changing how developers handle package installations is striking. Manual coding may have taken time, but with intelligent agents automating the background work, developers can focus on high-level tasks. The article categorizes common scenarios developers face in package decision-making: shared problems where robots excel, complex issues requiring thorough modeling, external dependencies needing ongoing maintenance, and opinionated frameworks shaping project direction. By understanding which problems to delegate to robots versus those that require human oversight, developers make smarter choices. The piece emphasizes a shift from finding solutions to knowing whether one wants to own a particular problem, marking a significant evolution in software development practices.&lt;/p&gt;
&lt;p&gt;Robots are taking over package handling, letting us focus on complex problems. Discover the four categories that define when to leverage this AI power.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://spatie.be/blog/the-robots-are-replacing-the-packages&quot;&gt;Continue reading on &lt;strong&gt;spatie.be&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-03T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-robots-are-replacing-the-packages</id>
    <title>🔗 The robots are replacing the packages</title>
    <updated>2026-06-03T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/why-crypto-getrandomvalues-matters-in-javascript" rel="alternate"/>
    <content type="html">&lt;p&gt;Generating random values sounds simple, until you need randomness that is actually secure.&lt;/p&gt;
&lt;p&gt;A lot of JavaScript developers reach for &lt;code&gt;Math.random()&lt;/code&gt; out of habit. While that works fine for visual effects, games, or non-critical IDs, it should never be used for anything security-sensitive.&lt;/p&gt;
&lt;p&gt;That’s where the Web Crypto API comes in.&lt;/p&gt;
&lt;h1&gt;The problem with &lt;code&gt;Math.random()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;Math.random()&lt;/code&gt; is not cryptographically secure.&lt;/p&gt;
&lt;p&gt;Its output is deterministic and predictable enough that an attacker may be able to reproduce or guess generated values under certain conditions.&lt;/p&gt;
&lt;p&gt;That makes it unsuitable for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Session tokens&lt;/li&gt;
&lt;li&gt;Password reset links&lt;/li&gt;
&lt;li&gt;API keys&lt;/li&gt;
&lt;li&gt;CSRF tokens&lt;/li&gt;
&lt;li&gt;Encryption keys&lt;/li&gt;
&lt;li&gt;Secure identifiers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-javascript&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;type-builtin&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This may look random, but it is not secure.&lt;/p&gt;
&lt;h1&gt;Using &lt;code&gt;crypto.getRandomValues()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Modern browsers provide a secure random number generator through the Web Crypto API.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-javascript&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;keyword-operator&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;constructor&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;crypto&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getRandomValues&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;&lt;span class=&quot;variable-builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This fills the typed array with cryptographically secure random bytes provided by the operating system.&lt;/p&gt;
&lt;h1&gt;Generating a secure random token&lt;/h1&gt;
&lt;p&gt;A common use case is generating secure tokens or identifiers.&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-javascript&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;keyword-function&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;function&quot;&gt;generateToken&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable-parameter&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;lbrace;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;keyword-operator&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;constructor&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;  &lt;span class=&quot;variable&quot;&gt;crypto&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getRandomValues&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;6&quot;&gt;  &lt;span class=&quot;keyword-return&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;type-builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;7&quot;&gt;    &lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable-parameter&quot;&gt;byte&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;padStart&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;8&quot;&gt;    &lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;9&quot;&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;&amp;rbrace;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;10&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;11&quot;&gt;&lt;span class=&quot;variable-builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;function-call&quot;&gt;generateToken&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example output:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;4f8b7d3a1f9e0c8d7a2b6c5d4e3f1a9c
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is significantly safer than using &lt;code&gt;Math.random()&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;Typed arrays are required&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;crypto.getRandomValues()&lt;/code&gt; only works with integer-based typed arrays.&lt;/p&gt;
&lt;p&gt;Supported examples include:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-javascript&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;keyword-operator&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;constructor&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;keyword-operator&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;constructor&quot;&gt;Uint16Array&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;keyword-operator&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;constructor&quot;&gt;Int32Array&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will fail:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-javascript&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;variable&quot;&gt;crypto&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getRandomValues&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because regular JavaScript arrays are not supported.&lt;/p&gt;
&lt;h1&gt;Browser and runtime support&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;crypto.getRandomValues()&lt;/code&gt; is widely supported in modern browsers.&lt;/p&gt;
&lt;p&gt;It is also available in runtimes like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Deno&lt;/li&gt;
&lt;li&gt;Bun&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example in Node.js:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-javascript&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;keyword-operator&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;constructor&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;2&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;variable&quot;&gt;crypto&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;getRandomValues&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;4&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; data-line=&quot;5&quot;&gt;&lt;span class=&quot;variable-builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In older Node.js versions, developers typically used:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-javascript&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;function-builtin&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&quot;crypto&quot;&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;randomBytes&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;UUID generation&lt;/h1&gt;
&lt;p&gt;If your goal is generating UUIDs, modern runtimes also support:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-javascript&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;variable&quot;&gt;crypto&lt;/span&gt;&lt;span class=&quot;punctuation-delimiter&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;function-method-call&quot;&gt;randomUUID&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;line&quot; data-line=&quot;1&quot;&gt;550e8400-e29b-41d4-a716-446655440000
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Internally, this also uses cryptographically secure randomness.&lt;/p&gt;
&lt;h1&gt;Things to remember&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;Math.random()&lt;/code&gt; for non-security-related randomness only&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;crypto.getRandomValues()&lt;/code&gt; for anything security-sensitive&lt;/li&gt;
&lt;li&gt;Prefer &lt;code&gt;crypto.randomUUID()&lt;/code&gt; when generating UUIDs&lt;/li&gt;
&lt;li&gt;Always generate randomness using the operating system’s secure RNG&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For modern JavaScript applications, &lt;code&gt;crypto.getRandomValues()&lt;/code&gt; should be the default choice whenever security matters.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/javascript&quot;&gt;#javascript&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/auth&quot;&gt;#auth&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-02T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/why-crypto-getrandomvalues-matters-in-javascript</id>
    <title>🐥 Why crypto.getRandomValues() matters in JavaScript</title>
    <updated>2026-06-02T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-language-of-the-boundary" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;The article discusses the development journey of creating a JSON Schema validator library for Elixir, detailing the complexities encountered when integrating JSON schema validation with Open API Spex. It emphasizes the necessity of validating data at boundaries, where untrusted external data is handled. The author, reflecting on past experiences, distinguishes between validating solely within Elixir and creating a shared understanding through JSON Schema among various programming teams, particularly in relation to Python and TypeScript. In exploring the challenges of maintaining and implementing validation rules effectively, the piece advocates for treating validation rules as data rather than as code, highlighting the importance of schemas as a means of ensuring compatibility and accuracy across different technologies. Ultimately, the author champions JSON Schema as the preferred solution for establishing clear, functional boundaries in application development.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://lud.codes/blog/why-i-wrote-a-json-schema-validation-library-for-elixir/&quot;&gt;Continue reading on &lt;strong&gt;lud.codes&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/elixir&quot;&gt;#elixir&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-02T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-language-of-the-boundary</id>
    <title>🔗 The language of the boundary</title>
    <updated>2026-06-02T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/ai-agents-keep-failing-the-fix-is-40-years-old" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;AI agents often falter due to hidden dependencies in the code, leading to failures in production environments. This issue stems not from the models themselves but from the tight coupling and mutable states in the codebase that AI agents cannot effectively navigate. As Cyrus Radfar points out, while human developers build mental models over time, AI lacks that context, resulting in complicating hidden states that cause cascading errors. To remedy this, he suggests applying long-established principles of functional programming from the 1980s. By ensuring that all functions are pure, with explicit data flows and minimal side effects, AI agents can operate more reliably in scenarios where codebases contain numerous dependencies. This approach enables agents to modify functions without facing the risk of unintended consequences from hidden global states. The implementation of these principles could significantly enhance AI-driven development practices.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://cyrusradfar.com/thoughts/functional-programming-is-the-only-way-to-scale-with-ai&quot;&gt;Continue reading on &lt;strong&gt;cyrusradfar.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-02T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/ai-agents-keep-failing-the-fix-is-40-years-old</id>
    <title>🔗 AI agents keep failing. The fix is 40 years old.</title>
    <updated>2026-06-02T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/claude-code-is-a-build-system-not-a-chatbot" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Claude Code redefines the interaction with AI coding by treating it as a build system rather than merely a chatbot. After a year of iteration, the author emphasizes the importance of treating AI like a configurable, layered, and observable engineering system. By moving from passive to active enforcement of coding standards and best practices, projects become less prone to errors, especially when attention drifts. The article explains how to set up automatic checks, the significance of writing standards clearly, and the benefits of using specialized subagents for tasks, plus future-proofing code through systematic hooks. With insights from the author&apos;s experiences across various programming languages, this piece serves as a guide to enhance AI-driven development and maintain consistency and quality in coding practices over time.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://vinny.dev/blog/2026-04-25-claude-code-build-system/&quot;&gt;Continue reading on &lt;strong&gt;vinny.dev&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/tools&quot;&gt;#tools&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-06-01T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/claude-code-is-a-build-system-not-a-chatbot</id>
    <title>🔗 Claude Code is a build system, not a chatbot</title>
    <updated>2026-06-01T17:00:00Z</updated>
  </entry>
</feed>