<?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-08-04T13:00:00Z</updated>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/rewriting-bun-in-rust" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Bun&apos;s evolution from Zig to Rust was not just a coding challenge; it aimed to resolve fundamental stability issues. The article details the ambitious journey of rewriting Bun&apos;s large codebase to enhance memory safety and eliminate bugs inherent in manual memory management. Originally a port from Go to Zig, the developer recognized weaknesses in Zig&apos;s handling of garbage-collected and manually-managed memory. By leveraging a new model from Anthropic, the team performed an efficient mechanical port to Rust, thus enabling safer code practices through Rust&apos;s strong type system and automatic memory management. The result? A more robust Bun, aiming for long-term stability and performance enhancement without sacrificing its original feature set. It&apos;s a case study in planning, execution, and leveraging AI in software development for increased reliability.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://bun.com/blog/bun-in-rust&quot;&gt;Continue reading on &lt;strong&gt;bun.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/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;/p&gt;</content>
    <published>2026-08-04T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/rewriting-bun-in-rust</id>
    <title>🔗 Rewriting Bun in Rust</title>
    <updated>2026-08-04T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/ever-run-into-a-postgresql-query-that-you-can-figure-out-what-it-does" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Ever encountered an indecipherable PostgreSQL query that you still need to support? This article outlines how DBeaver&apos;s AI Assistant can demystify complex queries for users. With DBeaver 26.1.2, the AI Assistant analyzes queries and provides understandable explanations. The author illustrates this tool&apos;s efficacy using a sample query that identifies the top 10 most popular films by rental count and total revenue. From common table expressions (CTEs) to subqueries, the breakdown makes clear how the query&apos;s elements interact to produce results, highlighting the AI&apos;s utility when faced with obfuscated SQL. This guide empowers developers and database administrators to tackle intimidating SQL queries with confidence, showcasing an essential feature for anyone working with PostgreSQL.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://stokerpostgresql.blogspot.com/2026/07/ever-run-into-postgresql-query-that-you.html&quot;&gt;Continue reading on &lt;strong&gt;stokerpostgresql.blogspot.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/database&quot;&gt;#database&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/postgresql&quot;&gt;#postgresql&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sql&quot;&gt;#sql&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-08-04T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/ever-run-into-a-postgresql-query-that-you-can-figure-out-what-it-does</id>
    <title>🔗 Ever run into a PostgreSQL query that you can figure out what it does??</title>
    <updated>2026-08-04T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/adding-2fa-to-phoenix-liveview-with-phx-gen-auth" rel="alternate"/>
    <content type="html">&lt;p&gt;Two-factor authentication (2FA) is a great way to improve account security. This post walks through how to add TOTP-based 2FA to a Phoenix LiveView app using the built-in &lt;code&gt;phx.gen.auth&lt;/code&gt; authentication system.&lt;/p&gt;
&lt;p&gt;We’ll cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adding required fields and dependencies&lt;/li&gt;
&lt;li&gt;2FA setup flow using LiveView&lt;/li&gt;
&lt;li&gt;TOTP challenge during login&lt;/li&gt;
&lt;li&gt;LiveView-specific login handling&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Add dependencies&lt;/h2&gt;
&lt;p&gt;Add the following libraries to &lt;code&gt;mix.exs&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-elixir&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-keyword-function&quot;&gt;defp&lt;/span&gt; &lt;span class=&quot;l-function&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;span class=&quot;l-punctuation-bracket&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;    &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:nimble_totp&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&quot;~&gt; 1.0&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:qr_code&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&quot;~&gt; 2.2&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;  &lt;span class=&quot;l-punctuation-bracket&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then run:&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;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;mix&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;deps.get&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Extend the user schema&lt;/h2&gt;
&lt;p&gt;Add two fields to your &lt;code&gt;users&lt;/code&gt; table:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-elixir&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-comment&quot;&gt;# priv/repo/migrations/*_add_totp_to_users.exs&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;alter&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;  &lt;span class=&quot;l-function-call&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:totp_secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:string&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;  &lt;span class=&quot;l-function-call&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:totp_confirmed_at&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:utc_datetime&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Migrate:&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;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;mix&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;ecto.migrate&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In your user schema:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-elixir&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;schema&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&quot;users&quot;&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;span class=&quot;l-function-call&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:totp_secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:string&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;  &lt;span class=&quot;l-function-call&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:totp_confirmed_at&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:utc_datetime&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;  &lt;span class=&quot;l-comment&quot;&gt;# ...&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ensure your &lt;code&gt;changeset/2&lt;/code&gt; casts these fields:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-elixir&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-keyword-function&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;l-function&quot;&gt;changeset&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;  &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;cast&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:totp_secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:totp_confirmed_at&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;  &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;validate_required&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Add 2FA setup LiveView&lt;/h2&gt;
&lt;p&gt;Create a new LiveView at &lt;code&gt;/settings/two_factor&lt;/code&gt; that generates a secret, renders a QR code, and lets the user enter their TOTP code.&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-elixir&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-keyword-function&quot;&gt;defmodule&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;MyAppWeb.TwoFactorSetupLive&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;MyAppWeb&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:live_view&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;NimbleTOTP&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;QRCode&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;MyApp.Accounts&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;  &lt;span class=&quot;l-keyword-function&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;l-function&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-comment&quot;&gt;_params&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-comment&quot;&gt;_session&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;8&quot;&gt;    &lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;assigns&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;current_user&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;9&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;10&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;totp_secret&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;11&quot;&gt;      &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:ok&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;setup?: &lt;/span&gt;&lt;span class=&quot;l-boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;12&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;else&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;13&quot;&gt;      &lt;span class=&quot;l-variable&quot;&gt;secret&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;encode32&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-module&quot;&gt;NimbleTOTP&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;14&quot;&gt;      &lt;span class=&quot;l-variable&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;NimbleTOTP&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;otpauth_uri&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;MyApp:&lt;/span&gt;&lt;span class=&quot;l-string-special&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;l-string-special&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;decode32!&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;issuer: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;MyApp&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;15&quot;&gt;      &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:ok&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;png&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;QRCode&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:png&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;16&quot;&gt;      &lt;span class=&quot;l-variable&quot;&gt;b64&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;encode64&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;png&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;17&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;18&quot;&gt;      &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:ok&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;19&quot;&gt;       &lt;span class=&quot;l-function-call&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;20&quot;&gt;         &lt;span class=&quot;l-string-special-symbol&quot;&gt;setup?: &lt;/span&gt;&lt;span class=&quot;l-boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;21&quot;&gt;         &lt;span class=&quot;l-string-special-symbol&quot;&gt;secret: &lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;22&quot;&gt;         &lt;span class=&quot;l-string-special-symbol&quot;&gt;qr_code: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;data:image/png;base64,&lt;/span&gt;&lt;span class=&quot;l-string-special&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;b64&lt;/span&gt;&lt;span class=&quot;l-string-special&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;23&quot;&gt;         &lt;span class=&quot;l-string-special-symbol&quot;&gt;code: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;24&quot;&gt;         &lt;span class=&quot;l-string-special-symbol&quot;&gt;error: &lt;/span&gt;&lt;span class=&quot;l-constant-builtin&quot;&gt;nil&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;25&quot;&gt;       &lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;26&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;27&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;28&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;29&quot;&gt;  &lt;span class=&quot;l-keyword-function&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;l-function&quot;&gt;handle_event&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;verify&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-special&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;code&quot;&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;30&quot;&gt;    &lt;span class=&quot;l-variable&quot;&gt;secret&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;decode32!&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;assigns&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;31&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;32&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;NimbleTOTP&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;valid?&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;33&quot;&gt;      &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:ok&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-comment&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;34&quot;&gt;        &lt;span class=&quot;l-module&quot;&gt;Accounts&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;update_user&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;assigns&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;current_user&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-special&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;35&quot;&gt;          &lt;span class=&quot;l-string-special-symbol&quot;&gt;totp_secret: &lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;assigns&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;36&quot;&gt;          &lt;span class=&quot;l-string-special-symbol&quot;&gt;totp_confirmed_at: &lt;/span&gt;&lt;span class=&quot;l-module&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;utc_now&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;37&quot;&gt;        &lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;38&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;39&quot;&gt;      &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:noreply&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;40&quot;&gt;       &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;41&quot;&gt;       &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;put_flash&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:info&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&quot;2FA enabled.&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;42&quot;&gt;       &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;push_redirect&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;to: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;/settings&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;43&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;else&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;44&quot;&gt;      &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:noreply&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;error: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;Invalid code&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;45&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;46&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;47&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-heex&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;!--&lt;/span&gt;&lt;span class=&quot;l-comment&quot;&gt; templates/two_factor_setup_live.html.heex &lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;--&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt;Two-Factor Authentication&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;%=&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;l-constant&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;setup?&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;l-tag-delimiter&quot;&gt;%&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;  &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt;Scan this QR code in your authenticator app:&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;  &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;l-tag-attribute&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;qr_code&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;l-tag-delimiter&quot;&gt;/&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;8&quot;&gt;  &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;l-tag-attribute&quot;&gt;phx-submit&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;verify&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;9&quot;&gt;    &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt;Code:&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;10&quot;&gt;    &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;l-tag-attribute&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;l-tag-attribute&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;l-tag-delimiter&quot;&gt;/&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;11&quot;&gt;    &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt;Verify&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;12&quot;&gt;  &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;13&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;14&quot;&gt;  &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;%=&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;l-constant&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;do: &lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;content_tag&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:p&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-constant&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;class: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;text-red-500&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt; %&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;15&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;%&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt; %&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;16&quot;&gt;  &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt;2FA is already enabled.&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;17&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;%&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt; %&gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Add a TOTP challenge LiveView&lt;/h2&gt;
&lt;p&gt;When a user logs in with 2FA enabled, redirect them to a LiveView at &lt;code&gt;/two_factor&lt;/code&gt; to enter their code.&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-elixir&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-keyword-function&quot;&gt;defmodule&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;MyAppWeb.TwoFactorChallengeLive&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;MyAppWeb&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;:live_view&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;MyApp.Accounts&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;NimbleTOTP&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;MyAppWeb.UserAuth&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;  &lt;span class=&quot;l-keyword-function&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;l-function&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-comment&quot;&gt;_params&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-special&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;pending_user_id&quot;&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;8&quot;&gt;    &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:ok&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;user: &lt;/span&gt;&lt;span class=&quot;l-module&quot;&gt;Accounts&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;get_user!&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;code: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;error: &lt;/span&gt;&lt;span class=&quot;l-constant-builtin&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;9&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;10&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;11&quot;&gt;  &lt;span class=&quot;l-keyword-function&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;l-function&quot;&gt;handle_event&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;verify&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-special&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;code&quot;&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;12&quot;&gt;    &lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;assigns&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;13&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;14&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;NimbleTOTP&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;valid?&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-module&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;decode32!&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;totp_secret&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;15&quot;&gt;      &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:noreply&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;16&quot;&gt;       &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;17&quot;&gt;       &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;put_flash&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:info&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&quot;Logged in with 2FA.&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;18&quot;&gt;       &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;UserAuth&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;log_in_user&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-special&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;19&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;else&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;20&quot;&gt;      &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:noreply&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;error: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;Invalid code&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;21&quot;&gt;    &lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;22&quot;&gt;  &lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;23&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-heex&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;!--&lt;/span&gt;&lt;span class=&quot;l-comment&quot;&gt; templates/two_factor_challenge_live.html.heex &lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;--&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt;Enter your 2FA code&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;l-tag-attribute&quot;&gt;phx-submit&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;verify&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;  &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;l-tag-attribute&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;l-tag-attribute&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;l-tag-delimiter&quot;&gt;/&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;  &lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt;Verify&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;l-tag&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;8&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;9&quot;&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt;&lt;%=&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;l-constant&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;do: &lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;content_tag&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:p&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-constant&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string-special-symbol&quot;&gt;class: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;text-red-500&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-tag-delimiter&quot;&gt; %&gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Update login logic&lt;/h2&gt;
&lt;p&gt;After validating the user’s password (in your LiveView or controller), check if TOTP is enabled:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-elixir&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;totp_confirmed_at&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;  &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;Phoenix.LiveView&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;put_session&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:pending_user_id&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;  &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;Phoenix.LiveView&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;to: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;/two_factor&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;else&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;  &lt;span class=&quot;l-module&quot;&gt;UserAuth&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;log_in_user&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-special&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In controllers, you’d use &lt;code&gt;put_session(conn, ...)&lt;/code&gt; and &lt;code&gt;redirect(conn, ...)&lt;/code&gt; instead.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Update &lt;code&gt;UserAuth&lt;/code&gt; helper&lt;/h2&gt;
&lt;p&gt;Make sure your &lt;code&gt;UserAuth&lt;/code&gt; module has a LiveView-compatible &lt;code&gt;log_in_user/3&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-elixir&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-keyword-function&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;l-function&quot;&gt;log_in_user&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-comment&quot;&gt;_params&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;\\&lt;/span&gt; &lt;span class=&quot;l-punctuation-special&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;span class=&quot;l-variable&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;MyApp.Accounts&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;generate_user_session_token&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;  &lt;span class=&quot;l-variable&quot;&gt;socket&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;  &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;Phoenix.LiveView&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;put_session&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;:user_token&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-variable&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;  &lt;span class=&quot;l-operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;l-module&quot;&gt;Phoenix.LiveView&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string-special-symbol&quot;&gt;to: &lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;&lt;span class=&quot;l-keyword&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;Done&lt;/h2&gt;
&lt;p&gt;You now have a working TOTP 2FA flow in Phoenix LiveView:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Users opt in to 2FA in their settings&lt;/li&gt;
&lt;li&gt;A QR code is shown and confirmed&lt;/li&gt;
&lt;li&gt;2FA is required on next login&lt;/li&gt;
&lt;li&gt;All handled with clean LiveView flows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From here, you can extend the system with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disabling 2FA&lt;/li&gt;
&lt;li&gt;Backup codes&lt;/li&gt;
&lt;li&gt;Remembering trusted devices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let me know if you&apos;d like a follow-up on any of those features.&lt;/p&gt;&lt;p&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/phoenix&quot;&gt;#phoenix&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-08-03T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/adding-2fa-to-phoenix-liveview-with-phx-gen-auth</id>
    <title>🐥 Adding 2FA to Phoenix LiveView with phx.gen.auth</title>
    <updated>2026-08-03T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/more-shell-patterns-i-use-weekly" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;This article shares useful Bash patterns and techniques that boost productivity for everyday tasks. The author highlights various methods like using &lt;code&gt;sed&lt;/code&gt; and &lt;code&gt;xargs&lt;/code&gt; for find-and-replace operations, employing &lt;code&gt;while&lt;/code&gt; loops until success, and parallelizing commands with &lt;code&gt;wait&lt;/code&gt;. The discussion emphasizes the importance of clean output and error handling, using temporary directories for logs with &lt;code&gt;mktemp&lt;/code&gt;, and enhancing user legibility with color-coded output. The author also advocates for efficient file manipulation using shell constructs, recommending &lt;code&gt;awk&lt;/code&gt; for filtering data instead of &lt;code&gt;grep&lt;/code&gt;. These patterns, though simple, can significantly streamline workflows, especially for those working with commands regularly.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://will-keleher.com/posts/more-shell-patterns-i-use-weekly/&quot;&gt;Continue reading on &lt;strong&gt;will-keleher.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;a href=&quot;https://www.yellowduck.be/tags/terminal&quot;&gt;#terminal&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/linux&quot;&gt;#linux&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-08-03T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/more-shell-patterns-i-use-weekly</id>
    <title>🔗 More shell patterns I use weekly</title>
    <updated>2026-08-03T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/why-backlogs-are-harmful-why-they-never-shrink-and-what-to-do-instead" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Backlogs never shrink, and their existence often leads to unproductive practices. When teams rely on them, they merely accumulate tasks that distract from prioritizing what truly matters. The article points out that important tasks rarely enter the backlog as teams instinctively know what needs immediate attention. This misalignment causes waste and elongates cycle times, as tasks languish unattended. A well-managed product team can avoid the pitfalls of backlogs by employing a high-level roadmap and maintaining close communication with engineers. In practice, this means regularly revisiting goals, effectively filtering bugs, and keeping the focus on immediate tasks. The author argues that instead of allowing unnecessary tasks to clutter workflows, it’s essential to be ruthless in prioritization and decision-making to enhance productivity and strategic alignment.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.lucasfcosta.com/blog/backlogs-are-useless&quot;&gt;Continue reading on &lt;strong&gt;www.lucasfcosta.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-08-03T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/why-backlogs-are-harmful-why-they-never-shrink-and-what-to-do-instead</id>
    <title>🔗 Why backlogs are harmful, why they never shrink, and what to do instead</title>
    <updated>2026-08-03T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-laravel-scheduler-under-the-hood" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Laravel&apos;s Scheduler features an API that simplifies task scheduling, but its underlying mechanics are crucial to understand. When cron triggers &lt;code&gt;php artisan schedule:run&lt;/code&gt;, Laravel takes over to determine which events are due. This article dives deep into the Laravel Scheduler, explaining how it processes scheduled tasks, from command definitions to execution. It clarifies concepts like &lt;code&gt;onOneServer()&lt;/code&gt; and &lt;code&gt;withoutOverlapping()&lt;/code&gt;, which are essential for managing concurrent tasks. Readers learn how Laravel creates event objects from command definitions and how frequency methods adjust cron expressions. The article emphasizes the distinctions between the Scheduler and the Queue system, underpinning the operational design decisions that make task scheduling effective in production environments. Armed with this insight, Laravel developers can better leverage the Scheduler for reliable task execution.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://wendelladriel.com/blog/the-laravel-scheduler-under-the-hood&quot;&gt;Continue reading on &lt;strong&gt;wendelladriel.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/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-08-02T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-laravel-scheduler-under-the-hood</id>
    <title>🔗 The Laravel Scheduler Under the Hood</title>
    <updated>2026-08-02T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/waze-now-supports-electric-vehicles-in-belgium" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Finding a charging station for your electric vehicle won&apos;t be difficult anymore. Waze has added full support for electric charging points on its map in Belgium, enabling users to enter their car and plug type. This upgrade allows Waze to pinpoint all available charging points in your vicinity or along your route.&lt;/p&gt;
&lt;p&gt;Thanks to the dedicated volunteer map editors, reliable information on charging points is now accessible. The community has worked tirelessly to update the Waze map with this critical data, ensuring it remains current. To configure electric vehicle support, users can navigate to Settings -&gt; Vehicle Details -&gt; Electric vehicles and toggle the EV features on, allowing them to easily find the nearest charging station. Users can also report outdated charging points for the community editors to review and update accordingly.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.wazebelgium.be/waze-now-supports-electric-vehicles-in-belgium/&quot;&gt;Continue reading on &lt;strong&gt;www.wazebelgium.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/announcement&quot;&gt;#announcement&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-08-02T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/waze-now-supports-electric-vehicles-in-belgium</id>
    <title>🔗 Waze now supports electric vehicles in Belgium</title>
    <updated>2026-08-02T13: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-sends-4-7x-more-tokens-than-opencode-before-reading-your-prompt" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Claude Code&apos;s appetite for tokens far exceeds that of OpenCode, as the article reveals startling figures from direct comparisons. In experiments run under identical conditions, Claude Code averaged around 33,000 tokens for a one-line reply, while OpenCode only consumed about 7,000. The data reported showcases how Claude Code’s approach introduces significant cache inefficiencies, requiring 54 times more tokens for some tasks. A primary concern raised is the impact on production environments, particularly when operating under regulations like the EU AI Act. The emphasis is on understanding the tokens spent is crucial for optimizing agentic AI systems, where every token represents context that can&apos;t be utilized for task completion. Additionally, analyzing not just input but also cache writes reveals the complexity and potential costs associated with these AI harnesses.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://systima.ai/blog/claude-code-vs-opencode-token-overhead&quot;&gt;Continue reading on &lt;strong&gt;systima.ai&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-08-02T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/claude-code-sends-4-7x-more-tokens-than-opencode-before-reading-your-prompt</id>
    <title>🔗 Claude Code sends 4.7x more tokens than OpenCode before reading your prompt</title>
    <updated>2026-08-02T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/software-has-changed" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;A surprising truth reveals how quickly the software landscape has transformed. In a recent tweet, Jamon Holmgren notes that many experienced engineers feel shell-shocked by these rapid changes. Development cycles are faster, yet there&apos;s a concern about not building the right things. The industry has shifted from deep focus to a management of constant new experiments, allowing for greater code review and refinement.&lt;/p&gt;
&lt;p&gt;Building faster doesn’t mean building better, but it does free up developers to tackle technical debt proactively. Holmgren reflects on this evolution, pondering the implications of how code is created versus its final quality. With the ability to learn and adapt, many are navigating this new landscape while aiming to produce trusted, quality code.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.abeautifulsite.net/posts/software-has-changed/&quot;&gt;Continue reading on &lt;strong&gt;www.abeautifulsite.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/best-practice&quot;&gt;#best-practice&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-08-01T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/software-has-changed</id>
    <title>🔗 Software has changed</title>
    <updated>2026-08-01T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/zig-creator-calls-spade-a-spade-anthropic-blows-smoke" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Anthropic&apos;s ambitious narrative suggests software engineering will vanish, backed by a staggering $132 billion investment and a looming IPO. However, skepticism is essential; with no profitability in sight, decisions based on such hype could lead to misguided architecture and staffing choices driven by fear. Andrew Kelley, the creator of Zig, openly criticized the migration of the Bun project from Zig to Rust, framing it as a marketing ploy rather than a technical necessity. This situation raises questions not only about the software&apos;s future but also about the reliability of narratives shaped by significant financial backing. With Bun’s heavy reliance on AI and the subsequent shift, the community now grapples with the implications of these choices in a world where every programming language is scrutinized against performance and credibility measures. The drama unfolds not just in technical decisions, but in the larger discourse around automation and responsibility in software development.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://raymyers.org/post/zed-creator-calls-spade-a-spade/&quot;&gt;Continue reading on &lt;strong&gt;raymyers.org&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;/p&gt;</content>
    <published>2026-08-01T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/zig-creator-calls-spade-a-spade-anthropic-blows-smoke</id>
    <title>🔗 Zig creator calls spade a spade, Anthropic blows smoke</title>
    <updated>2026-08-01T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/de-morgans-law" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Logical expressions can turn complex quickly, but understanding De Morgan’s Law can simplify them effectively. This principle, attributed to Augustus de Morgan in the 19th century, states that certain expressions using NOT, AND, and OR operations can be rewritten without changing their results. For instance, NOT(A) AND NOT(B) is equivalent to NOT(A OR B). Tracy Gilmore illustrates this concept with practical examples, including a detailed breakdown of truth tables and expressions. The article provides a clear guide on how to apply De Morgan’s Law to make code more readable and efficient. It&apos;s a valuable resource for programmers looking to improve their logical condition handling and streamline their code without the harsh symbols of Boolean algebra. Gilmore’s straightforward explanations make the law accessible for both seasoned developers and those newer to coding.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://dev.to/tracygjg/de-morgans-law-a-little-computer-science-for-the-inquisitive-developer-4m2k&quot;&gt;Continue reading on &lt;strong&gt;dev.to&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-08-01T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/de-morgans-law</id>
    <title>🔗 De Morgan’s Law</title>
    <updated>2026-08-01T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-order-of-data-defaults-performance-determinism-paging" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;What happens when an SQL query doesn&apos;t specify the &lt;code&gt;ORDER BY&lt;/code&gt; clause? This article breaks down the consequences of relying on the default sorting behavior across different databases such as Postgres, MySQL, and MongoDB. It illustrates with detailed SQL operations how Postgres defaults to insertion order, while MySQL may sort rows by primary key. It also points out the risks of assuming that the default order will remain consistent after updates or deletions. The author emphasizes that each database&apos;s handling of data ordering can affect performance and predictability, making it crucial for developers to be explicit in their ordering strategy.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://binaryigor.com/the-order-of-data.html&quot;&gt;Continue reading on &lt;strong&gt;binaryigor.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/database&quot;&gt;#database&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/sql&quot;&gt;#sql&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-07-31T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-order-of-data-defaults-performance-determinism-paging</id>
    <title>🔗 The Order of Data: defaults, performance, determinism &amp; paging</title>
    <updated>2026-07-31T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/small-programming-tricks" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Small nuggets of knowledge can significantly enhance engineering productivity. This article reveals useful programming tricks that don&apos;t require extensive prior knowledge. For instance, using &lt;code&gt;python3 -m http.server&lt;/code&gt; for quickly starting a simple server is highlighted. The author also suggests tools like &lt;code&gt;fzf&lt;/code&gt; for fuzzy searching terminal history, &lt;code&gt;atuin&lt;/code&gt; for a searchable SQLite database of shell history, and practical database commands such as &lt;code&gt;SELECT&lt;/code&gt; without a &lt;code&gt;FROM&lt;/code&gt;. Techniques in regular expressions, modern JavaScript capabilities, and efficient &lt;code&gt;git&lt;/code&gt; commands are discussed as well. These tricks emphasize that even minor insights can lead to substantial efficiency gains in programming tasks. Sharing these nuggets within teams can foster a culture of learning and continuous improvement. Inspired by Julia Evan&apos;s approach, the article emphasizes that small bits of knowledge are both powerful and enjoyable to learn.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://will-keleher.com/posts/small-programming-tricks-matter/&quot;&gt;Continue reading on &lt;strong&gt;will-keleher.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/python&quot;&gt;#python&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/terminal&quot;&gt;#terminal&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/git&quot;&gt;#git&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-07-31T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/small-programming-tricks</id>
    <title>🔗 Small programming tricks</title>
    <updated>2026-07-31T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/lucas-laws-of-project-management" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;A project’s success hinges on solving the actual problem, rather than solely adhering to a specification. Surprisingly, compliance with the initial scope is often misguided because the primary focus should be on user needs. As a project unfolds, the understanding of the problem evolves, necessitating adaptations in the solution. Prioritizing problem comprehension over rigid scope planning is key. As the article outlines, assumptions must be tested not for their ease but based on their potential cost if proven wrong. It emphasizes the importance of clear communication and shared understanding within the team, advocating for a streamlined backlog and adaptable plans. This method ensures that projects remain viable, meet deadlines, and continuously provide value throughout their lifecycle.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://lucasfcosta.com/blog/laws-of-software-project-management&quot;&gt;Continue reading on &lt;strong&gt;lucasfcosta.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-07-31T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/lucas-laws-of-project-management</id>
    <title>🔗 Lucas&apos; Laws of Project Management</title>
    <updated>2026-07-31T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/go-flavored-concurrency-in-c" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Go&apos;s concurrency model is attractive, but can it be mimicked in C using POSIX threads? This article delves into that question, exploring how to forge Go-like concurrency in C without runtime support and garbage collection. The writer introduces &lt;code&gt;Solod&lt;/code&gt;, a strict Go subset that compiles to C, utilizing POSIX thread constructs such as mutexes and condition variables as its foundation.&lt;/p&gt;
&lt;p&gt;The piece details various concurrency mechanisms like atomics, the worker pool, and task scheduling. Specific code snippets illustrate the direct translations from So to C, shedding light on performance trade-offs inherent to using OS threads versus lightweight goroutines. The core takeaway is clear: while achieving Go-like concurrency in C is challenging due to the shortcomings of POSIX threads, significant capabilities remain realizable by leveraging the right primitives and accepting the associated trade-offs.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://antonz.org/concurrency-in-c/&quot;&gt;Continue reading on &lt;strong&gt;antonz.org&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;/p&gt;</content>
    <published>2026-07-30T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/go-flavored-concurrency-in-c</id>
    <title>🔗 Go-flavored concurrency in C</title>
    <updated>2026-07-30T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/my-ai-learning-journey" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Metrics have always been the so-called magic beans for improving quality in testing and quality engineering. In her article, Lisa Crispin emphasizes the importance of measuring AI success and quality improvement. She shares her decades of experience in the field and highlights how continuous quality improvement is crucial for modern software teams. The discussion revolves around effective metrics that can drive quality initiatives, making the case for an analytical approach to testing. Crispin brings a fresh perspective on harnessing metrics to elevate both AI performance and overall product quality.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://lisacrispin.com/2026/07/10/my-ai-learning-journey/&quot;&gt;Continue reading on &lt;strong&gt;lisacrispin.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;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-07-30T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/my-ai-learning-journey</id>
    <title>🔗 My AI learning journey</title>
    <updated>2026-07-30T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/good-tools-are-delightful" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Good tools are designed with the user&apos;s needs in mind, leading to unexpected delight and increased productivity. Zach Daniel emphasizes how tools like Neovim create opportunities for learning and improvement, rather than simply fading into the background. He reflects on his own experience with plugins such as Neogit, which enhanced his understanding and efficiency in managing code. Daniel critiques the idea that effective tools should be invisible, arguing instead for tools that challenge users to grow. He also touches on the evolving landscape of tools with the rise of LLMs, noting their potential to streamline workflows without sacrificing depth. Ultimately, he champions the view that while good tools may disappear, the best ones empower and delight users.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.zachdaniel.dev/p/good-tools-are-delightful&quot;&gt;Continue reading on &lt;strong&gt;www.zachdaniel.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/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-07-30T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/good-tools-are-delightful</id>
    <title>🔗 Good tools are delightful</title>
    <updated>2026-07-30T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/two-database-migrations-and-a-divorce" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Jack Ellis narrates the journey of migrating Fathom Analytics to a new database structure while eliminating significant technical debt. This complex project, which involved moving over 65 billion rows, was accomplished by a single engineer. Ellis discusses the challenges faced, particularly concerning cookie laws, user privacy, and the evolution of their data ingestion model. A pivotal moment arose when they concluded that traditional methods of tracking unique visitors could not align with emerging privacy standards. The team innovated with daily salts and hashing, paving the way for a privacy-first approach in analytics. However, years of technical debt complicated their architecture, leading to issues like broken queries and inability to scale. The article provides detailed insights into the considerations and decisions that shaped this significant migration, reflecting on lessons learned and how they evolved their analytics solutions for better performance and privacy.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://usefathom.com/blog/two-database-migrations-and-a-divorce&quot;&gt;Continue reading on &lt;strong&gt;usefathom.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/database&quot;&gt;#database&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/devops&quot;&gt;#devops&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-07-29T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/two-database-migrations-and-a-divorce</id>
    <title>🔗 Two database migrations and a divorce</title>
    <updated>2026-07-29T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/claude-md-is-ram-not-disk" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Claude.md serves as working memory that needs to stay concise to remain effective. Alberto Arena highlights the pitfalls of allowing it to grow unwieldy, leading to reduced performance. Instead of cramming all information into this singular file, he advocates using it for essential, frequently required commands and pointers, while storing less frequently accessed information in separate documents. This distinction helps Claude manage context more efficiently and reduces unnecessary cognitive load. Applying this strategy means better interaction with the AI, as it has immediate access to crucial data while longer-term documentation resides in designated locations, unfettered by the immediate operational needs. Simplifying the architecture around how data is organized can significantly enhance coding workflows, especially in significant frameworks like Laravel.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://albertoarena.it/posts/claude-md-is-ram-not-disk/&quot;&gt;Continue reading on &lt;strong&gt;albertoarena.it&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/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;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-07-29T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/claude-md-is-ram-not-disk</id>
    <title>🔗 Claude.md is RAM, not disk</title>
    <updated>2026-07-29T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/i-think-i-have-llm-burnout" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Is burnout from large language models (LLMs) a real issue? The article reflects on the author&apos;s heavy usage of LLMs like Claude Code and Codex for daily tasks, expressing both productivity gains and mounting frustrations. After a year of constant interaction with AI-generated content, the author finds themselves increasingly annoyed by repetitive patterns, inaccuracies, and the overall style of LLM output—leading to feelings of fatigue towards these tools. Despite the productivity benefits, they acknowledge a shift in their disposition, grappling with the challenge of managing expectations and the limitations of LLMs. While the fascination remains, the growing irritation complicates their experience and relationship with AI.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.alecscollon.com/blog/llm-burnout/&quot;&gt;Continue reading on &lt;strong&gt;www.alecscollon.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-07-29T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/i-think-i-have-llm-burnout</id>
    <title>🔗 I think I have LLM burnout</title>
    <updated>2026-07-29T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/finding-unexpected-http-responses-in-json-logs-with-jq" rel="alternate"/>
    <content type="html">&lt;p&gt;When debugging an application in production, I often want a quick overview of requests that didn&apos;t result in a &quot;normal&quot; HTTP response. If your web server writes JSON logs, &lt;code&gt;jq&lt;/code&gt; makes this incredibly easy.&lt;/p&gt;
&lt;p&gt;Here&apos;s a command I regularly 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;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;access_*.log&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt; \
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;jq&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&amp;#39;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;      select(
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;        .status != 200 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;        .status != 206 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;        .status != 302 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;        .status != 304 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;8&quot;&gt;        .status != 308 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;9&quot;&gt;        .status != 101
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;10&quot;&gt;      )
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;11&quot;&gt;      | [.status, .request.uri]
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;12&quot;&gt;      | @csv
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;13&quot;&gt;    &amp;#39;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt; \
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;14&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;uniq&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output looks something like this:&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;l-line&quot; data-line=&quot;1&quot;&gt;404,&quot;/api/v1/users/...&quot;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;403,&quot;/admin/...&quot;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;429,&quot;/api/v1/search&quot;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;500,&quot;/api/v1/orders/...&quot;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;What this does&lt;/h1&gt;
&lt;p&gt;The command performs three simple steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reads all matching access log files.&lt;/li&gt;
&lt;li&gt;Filters out the expected HTTP status codes (&lt;code&gt;200&lt;/code&gt;, &lt;code&gt;206&lt;/code&gt;, &lt;code&gt;302&lt;/code&gt;, &lt;code&gt;304&lt;/code&gt;, &lt;code&gt;308&lt;/code&gt;, and &lt;code&gt;101&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Outputs the remaining status code together with the requested URI as CSV.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, &lt;code&gt;uniq&lt;/code&gt; removes duplicate entries so you get a concise overview instead of thousands of repeated requests.&lt;/p&gt;
&lt;h1&gt;Why this is useful&lt;/h1&gt;
&lt;p&gt;This is an easy way to spot things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Missing routes (&lt;code&gt;404&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Authorization issues (&lt;code&gt;401&lt;/code&gt;/&lt;code&gt;403&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Rate limiting (&lt;code&gt;429&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Unexpected server errors (&lt;code&gt;500&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Any other response that deserves investigation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead of searching through millions of log lines, you immediately get a list of unique problem endpoints.&lt;/p&gt;
&lt;h1&gt;A small improvement&lt;/h1&gt;
&lt;p&gt;If your logs aren&apos;t already grouped, consider sorting before calling &lt;code&gt;uniq&lt;/code&gt;:&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;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;access_*.log&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt; \
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;jq&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&amp;#39;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;      select(
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;        .status != 200 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;        .status != 206 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;        .status != 302 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;        .status != 304 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;8&quot;&gt;        .status != 308 and
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;9&quot;&gt;        .status != 101
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;10&quot;&gt;      )
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;11&quot;&gt;      | [.status, .request.uri]
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;12&quot;&gt;      | @csv
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;13&quot;&gt;    &amp;#39;&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt; \
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;14&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;l-text&quot;&gt; \
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;15&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;uniq&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, even shorter:&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;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;...&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;l-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;-u&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s a simple one-liner, but it&apos;s become one of my favourite ways to quickly identify unexpected responses in production logs.&lt;/p&gt;&lt;p&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/logging&quot;&gt;#logging&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-07-28T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/finding-unexpected-http-responses-in-json-logs-with-jq</id>
    <title>🐥 Finding unexpected HTTP responses in JSON logs with jq</title>
    <updated>2026-07-28T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/http-query-method-support-in-laravel-13-19" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Laravel 13.19.0 introduces support for the HTTP QUERY method across its HTTP client and testing helpers. The new &lt;code&gt;Http::query()&lt;/code&gt; method allows users to issue QUERY requests, sending parameters in the request body rather than the URL. This mirrors existing methods like &lt;code&gt;post()&lt;/code&gt;, &lt;code&gt;put()&lt;/code&gt;, and &lt;code&gt;patch()&lt;/code&gt; and defaults to sending JSON data.&lt;/p&gt;
&lt;p&gt;The article also covers new testing helpers: &lt;code&gt;query()&lt;/code&gt; and &lt;code&gt;queryJson()&lt;/code&gt;, which facilitate testing routes that respond to QUERY requests. Additionally, a new collection method, &lt;code&gt;reduceInto()&lt;/code&gt;, is introduced for more effective accumulator handling. Other enhancements include the &lt;code&gt;counted()&lt;/code&gt; string helper to streamline word pluralization, bulk SQS dispatch improvements, and numerous bug fixes and optimizations. This release reflects Laravel&apos;s commitment to evolving and refining its framework.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://laravel-news.com/laravel-13-19-0&quot;&gt;Continue reading on &lt;strong&gt;laravel-news.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/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/http&quot;&gt;#http&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-07-28T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/http-query-method-support-in-laravel-13-19</id>
    <title>🔗 HTTP query method support in Laravel 13.19</title>
    <updated>2026-07-28T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/tower-17-for-mac-beta-smarter-fully-merged-detection" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Tower 17 for Mac, now in Beta, introduces significantly smarter &quot;Fully Merged&quot; detection. This update allows Tower to match local branches against merged pull requests from hosting services like GitHub and GitLab. Previously, users faced uncertainty when deleting branches that were squash or rebase merged, leading to cluttered projects with irrelevant branches. With this release, Tower employs advanced checks, including Git&apos;s classic merge detection and merge commit analysis, to accurately identify if branches are fully merged.&lt;/p&gt;
&lt;p&gt;The redesigned hint view enhances transparency, showing exactly which checks applied when determining if a branch can be safely deleted. Users can also quickly access merge commits or pull requests for verification. Additional improvements enhance the application’s performance, particularly in updating submodules. Tower&apos;s new features aim to streamline users&apos; workflows and make branch management safer and more intuitive.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.git-tower.com/blog/tower-mac-17&quot;&gt;Continue reading on &lt;strong&gt;www.git-tower.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/tools&quot;&gt;#tools&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/git&quot;&gt;#git&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-07-28T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/tower-17-for-mac-beta-smarter-fully-merged-detection</id>
    <title>🔗 Tower 17 for Mac (Beta) — smarter &quot;fully merged&quot; detection</title>
    <updated>2026-07-28T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/announcing-typescript-7-0" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;TypeScript 7 has arrived, boasting a native port that is reported to be 10 times faster than its predecessor. This major rewrite was done in Go, allowing it to leverage modern hardware effectively. Developers can expect significant speedups in various operations like &lt;code&gt;find-all-references&lt;/code&gt;, auto-completions, and diagnostics, with build times seeing improvements between 8x and 12x on common open-source projects. Notably, TypeScript 7 is designed for seamless integration with popular editors such as VS Code and Visual Studio. Initial tests reveal the new version reduces memory usage while enhancing responsiveness. Major companies, including Google and Microsoft, have tested and adopted TypeScript 7, reporting drastically improved performance. As it currently stands, TypeScript 7 can run alongside version 6, ensuring a smooth transition for ongoing projects. Tight feedback loops and aggressive testing have also bolstered quality, making this release one of the most stable yet.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/&quot;&gt;Continue reading on &lt;strong&gt;devblogs.microsoft.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/typescript&quot;&gt;#typescript&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/announcement&quot;&gt;#announcement&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-07-27T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/announcing-typescript-7-0</id>
    <title>🔗 Announcing TypeScript 7.0</title>
    <updated>2026-07-27T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-four-horsemen-behind-thousands-of-postgres-outages" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Postgres outages often stem from preventable issues related to vacuum operations, connection limits, and query planning. Many startups face downtime due to insufficient handling of transaction ID wraparound and I/O competition caused by vacuum processes. The author highlights innovative solutions through &lt;code&gt;pgrust&lt;/code&gt;, a reimplementation of Postgres, which aims to offer a modern architecture, including 64-bit transaction IDs and thread-based processing for better resource management. The article emphasizes the challenges posed by bad query plans and the need for improved JSON handling, acknowledging the frustrations caused by the existing limitations in Postgres. This proactive approach promises to address common pain points faced by users in real-world applications.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://malisper.me/the-four-horsemen-behind-thousands-of-postgres-outages/&quot;&gt;Continue reading on &lt;strong&gt;malisper.me&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/database&quot;&gt;#database&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/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-07-27T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-four-horsemen-behind-thousands-of-postgres-outages</id>
    <title>🔗 The four horsemen behind thousands of Postgres outages</title>
    <updated>2026-07-27T13:00:00Z</updated>
  </entry>
</feed>