<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aral Roca</title>
    <description>The latest articles on DEV Community by Aral Roca (@aralroca).</description>
    <link>https://dev.to/aralroca</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F51056%2Fe0e242b1-fc41-4f88-8163-629ee7692ecd.jpeg</url>
      <title>DEV Community: Aral Roca</title>
      <link>https://dev.to/aralroca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aralroca"/>
    <language>en</language>
    <item>
      <title>I Stopped Installing Qiskit to Understand Hadamard Gates</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Wed, 22 Apr 2026 18:53:44 +0000</pubDate>
      <link>https://dev.to/aralroca/i-stopped-installing-qiskit-to-understand-hadamard-gates-1m8n</link>
      <guid>https://dev.to/aralroca/i-stopped-installing-qiskit-to-understand-hadamard-gates-1m8n</guid>
      <description>&lt;p&gt;I spent six years working adjacent to quantum computing research. Not building qubits; building the classical software that talks to the hardware. The thing that surprised me most wasn't the physics. It was how bad the tooling was for anyone trying to &lt;em&gt;learn&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The education gap is the real bottleneck
&lt;/h2&gt;

&lt;p&gt;The hardware is advancing. &lt;a href="https://research.ibm.com/blog/next-wave-quantum-centric-supercomputing" rel="noopener noreferrer"&gt;IBM's 1,121-qubit Condor processor&lt;/a&gt; exists. Google's Willow chip hit a &lt;a href="https://blog.google/technology/research/google-willow-quantum-chip/" rel="noopener noreferrer"&gt;below-threshold error correction milestone&lt;/a&gt; in late 2024. But ask a CS undergrad to explain what a Hadamard gate actually does to a qubit's state vector, and you'll get a blank stare followed by a memorized sentence from a textbook.&lt;/p&gt;

&lt;p&gt;The problem isn't intelligence. The problem is that every learning path for quantum circuits funnels you into one of two dead ends:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Pen-and-paper linear algebra.&lt;/strong&gt; You compute tensor products by hand. You multiply 8x8 matrices. By the time you've verified that your CNOT gate works correctly, you've spent 40 minutes and lost all intuition for what the circuit &lt;em&gt;does&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Full SDK installations.&lt;/strong&gt; &lt;a href="https://qiskit.org/" rel="noopener noreferrer"&gt;Qiskit&lt;/a&gt;, &lt;a href="https://quantumai.google/cirq" rel="noopener noreferrer"&gt;Cirq&lt;/a&gt;, &lt;a href="https://pennylane.ai/" rel="noopener noreferrer"&gt;PennyLane&lt;/a&gt;. These are serious tools for serious work. They're also 200MB+ installs with Python dependency chains, Jupyter notebooks, and a learning curve that assumes you already understand what you're trying to learn. That's backwards.&lt;/p&gt;

&lt;p&gt;There's a gap between "read the textbook" and "install Qiskit." That gap is where most people give up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually wanted
&lt;/h2&gt;

&lt;p&gt;A textarea where I type &lt;code&gt;H 0&lt;/code&gt; and immediately see the state vector change. No install. No signup. No notebook server. Just a browser tab. And if I don't remember the syntax, a row of clickable buttons that writes the gate for me.&lt;/p&gt;

&lt;p&gt;That's what the &lt;a href="https://kitmul.com/en/visualizers-logic/quantum-circuit-simulator" rel="noopener noreferrer"&gt;Quantum Circuit Simulator&lt;/a&gt; is. Up to 16 qubits, nine gates (H, X, Y, Z, S, T, CX, SWAP, CCX), a gate toolbar for quick insertion, real-time probability bars, complex amplitudes, and an interactive 3D Bloch sphere that shows each qubit's state on the unit sphere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthj3nayzplwzkjzedsq3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthj3nayzplwzkjzedsq3.webp" alt="The simulator showing a Bell State circuit with clickable gate toolbar, probability bars, amplitudes, and a 3D Bloch sphere where both entangled qubits sit at the origin" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The syntax is one gate per line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H 0
CX 0 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a &lt;a href="https://en.wikipedia.org/wiki/Bell_state" rel="noopener noreferrer"&gt;Bell State&lt;/a&gt;. Two lines. The output shows &lt;code&gt;|00&amp;gt;&lt;/code&gt; at 50.00% and &lt;code&gt;|11&amp;gt;&lt;/code&gt; at 50.00%, with amplitudes of 0.707 + 0.000i each. If you've read Nielsen &amp;amp; Chuang, you recognize this as (1/sqrt(2))(|00&amp;gt; + |11&amp;gt;); the maximally entangled two-qubit state that Einstein called "spooky action at a distance."&lt;/p&gt;

&lt;p&gt;You didn't need to install anything to see that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why browser-based matters for quantum education
&lt;/h2&gt;

&lt;p&gt;There's a pedagogical argument here that goes beyond convenience. When the feedback loop between "write circuit" and "see result" drops to zero seconds, something changes in how you learn.&lt;/p&gt;

&lt;p&gt;You start experimenting. You add a Z gate after the Hadamard and watch the probabilities shift. You swap the control and target qubits on the CNOT and see what breaks. You build a &lt;a href="https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state" rel="noopener noreferrer"&gt;GHZ state&lt;/a&gt; with three qubits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H 0
CX 0 1
CX 1 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you see &lt;code&gt;|000&amp;gt;&lt;/code&gt; at 50% and &lt;code&gt;|111&amp;gt;&lt;/code&gt; at 50%; all three qubits entangled, no intermediate states. The 0.707 amplitude on both basis states confirms the math. You didn't need to set up a virtual environment to get there.&lt;/p&gt;

&lt;p&gt;This is how people actually learn. Not by reading about superposition in a PDF; by breaking circuits and watching what happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  The technical implementation
&lt;/h2&gt;

&lt;p&gt;The simulator runs entirely in JavaScript. No backend. No WebAssembly. No WASM-compiled Qiskit. Just matrix multiplication on complex numbers in the browser.&lt;/p&gt;

&lt;p&gt;The state vector starts as &lt;code&gt;|000...0&amp;gt;&lt;/code&gt; (all qubits in the &lt;code&gt;|0&amp;gt;&lt;/code&gt; state). Each gate applies a unitary transformation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hadamard (H)&lt;/strong&gt;: Creates superposition. Transforms &lt;code&gt;|0&amp;gt;&lt;/code&gt; into (|0&amp;gt; + |1&amp;gt;)/sqrt(2).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pauli-X&lt;/strong&gt;: Quantum NOT gate. Flips &lt;code&gt;|0&amp;gt;&lt;/code&gt; to &lt;code&gt;|1&amp;gt;&lt;/code&gt; and vice versa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pauli-Y&lt;/strong&gt;: Rotation around the Y-axis with a phase factor of &lt;em&gt;i&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pauli-Z&lt;/strong&gt;: Phase flip. Leaves &lt;code&gt;|0&amp;gt;&lt;/code&gt; unchanged but maps &lt;code&gt;|1&amp;gt;&lt;/code&gt; to -&lt;code&gt;|1&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CX (CNOT)&lt;/strong&gt;: Controlled-NOT. Flips the target qubit if and only if the control qubit is &lt;code&gt;|1&amp;gt;&lt;/code&gt;. This is the gate that creates entanglement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase (S)&lt;/strong&gt;: Rotates by π/2 around the Z-axis. Maps |1⟩ to i|1⟩. The square root of Z.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;T (π/8 gate)&lt;/strong&gt;: Rotates by π/4 around the Z-axis. Key building block for universal quantum computation. The square root of S.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SWAP&lt;/strong&gt;: Exchanges the states of two qubits. Syntax: &lt;code&gt;SWAP q1 q2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CCX (Toffoli)&lt;/strong&gt;: Controlled-controlled-NOT. Flips the target qubit only when both control qubits are |1⟩. Universal for classical reversible computation. Syntax: &lt;code&gt;CCX c1 c2 target&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a 3-qubit system, the state vector has 2^3 = 8 complex amplitudes. The simulator tracks all of them and displays both the raw amplitudes and the measurement probabilities (|amplitude|^2) in real time.&lt;/p&gt;

&lt;p&gt;The circuit state is encoded into the URL. Every change you make; every gate you add, every qubit count adjustment; updates the URL parameters automatically. Copy the URL, send it to a colleague, and they see your exact circuit. No accounts. No save buttons. No cloud storage. The URL &lt;em&gt;is&lt;/em&gt; the save file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gate toolbar and Bloch sphere
&lt;/h2&gt;

&lt;p&gt;Two things kept bugging me about text-only circuit input. First, beginners don't know the syntax. Second, numbers alone don't build geometric intuition about qubit states.&lt;/p&gt;

&lt;p&gt;The gate toolbar sits above the textarea: nine buttons grouped by type (single-qubit: H, X, Y, Z, S, T; two-qubit: CX, SWAP; three-qubit: CCX). Click a button and the gate line gets appended to your circuit. You can still type manually if you prefer, but the buttons remove the "what was the syntax for a Toffoli gate again?" friction.&lt;/p&gt;

&lt;p&gt;The Bloch sphere renders below the results panel. It computes the reduced density matrix for each qubit via partial trace, then extracts the Bloch coordinates (x = 2Re(rho01), y = 2Im(rho01), z = rho00 - rho11). For a single qubit in &lt;code&gt;|0&amp;gt;&lt;/code&gt;, the vector points to the north pole. Apply a Hadamard and it moves to the equator. Create a Bell state and both vectors collapse to the origin, because the reduced state of each qubit in a maximally entangled pair is the maximally mixed state. You can drag the sphere to rotate it, which helps when multiple qubit vectors overlap.&lt;/p&gt;

&lt;p&gt;For circuits with 1 to 4 qubits, all vectors show on the same sphere with different colors. Beyond 4 qubits, a dropdown lets you pick which qubit to visualize.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing to the alternatives
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Kitmul Simulator&lt;/th&gt;
&lt;th&gt;Qiskit&lt;/th&gt;
&lt;th&gt;Cirq&lt;/th&gt;
&lt;th&gt;IBM Quantum Composer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;0 seconds&lt;/td&gt;
&lt;td&gt;10-30 min&lt;/td&gt;
&lt;td&gt;10-30 min&lt;/td&gt;
&lt;td&gt;Account required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Install size&lt;/td&gt;
&lt;td&gt;0 MB&lt;/td&gt;
&lt;td&gt;~500 MB&lt;/td&gt;
&lt;td&gt;~300 MB&lt;/td&gt;
&lt;td&gt;Cloud-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max qubits&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;127 (hardware)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sharing&lt;/td&gt;
&lt;td&gt;URL copy&lt;/td&gt;
&lt;td&gt;Export notebook&lt;/td&gt;
&lt;td&gt;Export script&lt;/td&gt;
&lt;td&gt;Account link&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy&lt;/td&gt;
&lt;td&gt;100% local&lt;/td&gt;
&lt;td&gt;Local&lt;/td&gt;
&lt;td&gt;Local&lt;/td&gt;
&lt;td&gt;IBM cloud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free tier limited&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The trade-off is obvious. The Kitmul simulator handles up to 16 qubits. Qiskit handles 30. If you're implementing &lt;a href="https://en.wikipedia.org/wiki/Shor%27s_algorithm" rel="noopener noreferrer"&gt;Shor's algorithm&lt;/a&gt; or running variational quantum eigensolvers, you need the full SDK. If you're trying to understand what a Hadamard gate does before committing to a 500MB install, you don't.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasir7tsp6euw61omv4hd.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasir7tsp6euw61omv4hd.webp" alt="A quantum computer cryostat chandelier; gold-plated copper wiring and superconducting coils cooled to millikelvins above absolute zero" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Eight circuits worth trying
&lt;/h2&gt;

&lt;p&gt;Here are eight circuits you can paste directly into the &lt;a href="https://kitmul.com/en/visualizers-logic/quantum-circuit-simulator" rel="noopener noreferrer"&gt;simulator&lt;/a&gt; (or build them by clicking the gate buttons):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Superposition on a single qubit&lt;/strong&gt; (set qubits to 1):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;|0&amp;gt;&lt;/code&gt; and &lt;code&gt;|1&amp;gt;&lt;/code&gt; each at 50%. This is the quantum coin flip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Bell State&lt;/strong&gt; (set qubits to 2):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H 0
CX 0 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;|00&amp;gt;&lt;/code&gt; and &lt;code&gt;|11&amp;gt;&lt;/code&gt; each at 50%. Maximal entanglement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. GHZ State&lt;/strong&gt; (set qubits to 3):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H 0
CX 0 1
CX 1 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;|000&amp;gt;&lt;/code&gt; and &lt;code&gt;|111&amp;gt;&lt;/code&gt; each at 50%. Three-qubit entanglement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Phase kickback&lt;/strong&gt; (set qubits to 2):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X 1
H 0
CX 0 1
H 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: The Hadamard-CNOT-Hadamard sandwich. Watch how the phase of the target qubit kicks back to the control. This is the core mechanism behind &lt;a href="https://en.wikipedia.org/wiki/Deutsch%E2%80%93Jozsa_algorithm" rel="noopener noreferrer"&gt;Deutsch's algorithm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Quantum NOT with Hadamard&lt;/strong&gt; (set qubits to 1):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H 0
Z 0
H 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;|1&amp;gt;&lt;/code&gt; at 100%. The H-Z-H sequence is equivalent to a Pauli-X gate. This identity (HZH = X) shows up everywhere in quantum error correction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Phase gate demo&lt;/strong&gt; (set qubits to 1):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X 0
S 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;|1&amp;gt;&lt;/code&gt; at 100%, but the amplitude is now &lt;code&gt;0.000 + 1.000i&lt;/code&gt;. The S gate adds a π/2 phase rotation. Compare with Z (which maps |1⟩ to -|1⟩).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Toffoli gate — quantum AND&lt;/strong&gt; (set qubits to 3):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X 0
X 1
CCX 0 1 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;|111&amp;gt;&lt;/code&gt; at 100%. The Toffoli gate flips qubit 2 only when both qubits 0 and 1 are &lt;code&gt;|1&amp;gt;&lt;/code&gt;. This is the reversible equivalent of a classical AND gate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. SWAP circuit&lt;/strong&gt; (set qubits to 2):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X 0
SWAP 0 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;|01&amp;gt;&lt;/code&gt; at 100%. The state that was on qubit 0 has been transferred to qubit 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is for
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CS students&lt;/strong&gt; taking their first quantum computing course. The simulator covers exactly what shows up in chapters 1-4 of &lt;a href="https://en.wikipedia.org/wiki/Quantum_Computation_and_Quantum_Information" rel="noopener noreferrer"&gt;Nielsen &amp;amp; Chuang&lt;/a&gt;; single-qubit gates, multi-qubit gates, entanglement, and measurement probabilities. The gate toolbar means you don't need to memorize syntax on day one, and the Bloch sphere gives you the geometric picture that textbooks struggle to convey in static figures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Software engineers&lt;/strong&gt; curious about quantum computing but not ready to commit to a full SDK installation. You can verify your intuition in 30 seconds and then decide if it's worth going deeper with Qiskit or Cirq.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Physics students&lt;/strong&gt; who understand the math but want to quickly prototype small circuits without booting up Jupyter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teachers&lt;/strong&gt; who need a zero-friction demo tool for lectures. Share a URL; students see the circuit on their own devices. No lab setup. No installation instructions. No "my Python version is different" support tickets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy
&lt;/h2&gt;

&lt;p&gt;The entire simulation runs in your browser's JavaScript engine. No circuit data is transmitted to any server. No analytics track which gates you use. The URL encoding uses base64, which is decoded client-side. If you're working with proprietary circuit designs (up to 16 qubits), nothing leaves your device.&lt;/p&gt;

&lt;p&gt;If you want to explore other tools in the same category, the &lt;a href="https://dev.to/en/visualizers-logic"&gt;Visualizers &amp;amp; Logic Tools collection&lt;/a&gt; includes graph visualizers, truth tables, and logic gate simulators that pair well with quantum circuit work. For tracking your study sessions, the &lt;a href="https://dev.to/en/agile-project-management/pomodoro-agile"&gt;Pomodoro Timer&lt;/a&gt; with built-in focus music works surprisingly well for problem sets.&lt;/p&gt;

&lt;h2&gt;
  
  
  The point
&lt;/h2&gt;

&lt;p&gt;Quantum computing doesn't need to be gatekept by tooling complexity. The fundamental operations; Hadamard, Pauli gates, CNOT; are matrix multiplications. A browser can do matrix multiplication. So a browser can simulate small quantum circuits. And with a clickable gate toolbar and an interactive Bloch sphere, the barrier to entry drops even further.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/visualizers-logic/quantum-circuit-simulator" rel="noopener noreferrer"&gt;Quantum Circuit Simulator&lt;/a&gt; won't replace Qiskit for research. It replaces the 30 minutes between "I wonder what happens if I apply H then CX" and actually seeing the answer. For learning, that's everything.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The Quantum Circuit Simulator is free, private, and runs entirely in your browser. No signup, no install, no data leaves your device. Part of the &lt;a href="https://dev.to/en/visualizers-logic"&gt;Visualizers &amp;amp; Logic Tools&lt;/a&gt; collection on Kitmul. Photos by &lt;a href="https://unsplash.com/@alexshuper" rel="noopener noreferrer"&gt;Alex Shuper&lt;/a&gt; and &lt;a href="https://unsplash.com/@dynamicwang" rel="noopener noreferrer"&gt;Dynamic Wang&lt;/a&gt; on Unsplash.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>quantum</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Tracked My To-Do List for 30 Days. 73% of My 'Urgent' Work Was Someone Else's Emergency.</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Tue, 21 Apr 2026 19:22:47 +0000</pubDate>
      <link>https://dev.to/aralroca/i-tracked-my-to-do-list-for-30-days-73-of-my-urgent-work-was-someone-elses-emergency-63</link>
      <guid>https://dev.to/aralroca/i-tracked-my-to-do-list-for-30-days-73-of-my-urgent-work-was-someone-elses-emergency-63</guid>
      <description>&lt;p&gt;I tracked every task I touched for 30 days. Not in a project management tool; in a spreadsheet with three columns: task, time spent, and whether it actually mattered a week later.&lt;/p&gt;

&lt;p&gt;The results were embarrassing. 73% of the tasks I labeled "urgent" on Monday were irrelevant by Friday. Most of them were other people's priorities that I adopted because they arrived with exclamation marks in the subject line. The remaining 27%; the things that actually moved my projects forward; had been sitting in my backlog for weeks, quietly aging while I answered Teams threads.&lt;/p&gt;

&lt;p&gt;That spreadsheet is why I stopped using to-do lists and started using the &lt;a href="https://kitmul.com/en/agile-project-management/eisenhower-matrix" rel="noopener noreferrer"&gt;Eisenhower Matrix&lt;/a&gt;. Not because I read a productivity book. Because the data made it impossible to keep pretending that busy equals productive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The urgent-important confusion
&lt;/h2&gt;

&lt;p&gt;Most people use the words "urgent" and "important" interchangeably. They're not. &lt;a href="https://en.wikipedia.org/wiki/Dwight_D._Eisenhower" rel="noopener noreferrer"&gt;Dwight Eisenhower&lt;/a&gt; understood this distinction better than anyone in the 20th century. The man commanded D-Day, served as NATO's first Supreme Commander, and ran the United States for eight years. His productivity wasn't a lifestyle hack; it was a survival requirement.&lt;/p&gt;

&lt;p&gt;His insight was simple: &lt;strong&gt;urgent means it demands attention now. Important means it contributes to your long-term goals.&lt;/strong&gt; These two axes are independent. A task can be both, either, or neither.&lt;/p&gt;

&lt;p&gt;The problem is that urgency hijacks your attention. A ringing phone feels more important than a strategic plan because your brain evolved to respond to immediate stimuli. &lt;a href="https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow" rel="noopener noreferrer"&gt;Daniel Kahneman&lt;/a&gt; calls this System 1 thinking; fast, automatic, and terrible at prioritization. Every time you react to an urgent-but-unimportant task, you're letting your amygdala run your calendar.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four quadrants
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/agile-project-management/eisenhower-matrix" rel="noopener noreferrer"&gt;Eisenhower Matrix&lt;/a&gt; sorts every task into one of four quadrants:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q1: Urgent + Important (Do First)&lt;/strong&gt;&lt;br&gt;
Deadlines, crises, client emergencies. A production server is down. A contract expires tomorrow. These need immediate action and actually matter. The trap: if Q1 is always full, you're not prioritizing; you're firefighting. That means your Q2 is neglected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2: Not Urgent + Important (Schedule)&lt;/strong&gt;&lt;br&gt;
Strategic planning. Skill development. Relationship building. Exercise. Writing documentation. These tasks never scream at you, which is exactly why most people ignore them until they become Q1 crises. &lt;a href="https://en.wikipedia.org/wiki/The_7_Habits_of_Highly_Effective_People" rel="noopener noreferrer"&gt;Stephen Covey&lt;/a&gt; argued that Q2 is where your career lives. He was right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3: Urgent + Not Important (Delegate)&lt;/strong&gt;&lt;br&gt;
Most meetings. Most emails. Someone else's deadline that landed in your inbox. These feel urgent because another human being is waiting, but they don't move &lt;em&gt;your&lt;/em&gt; goals forward. Delegate them, batch them, or set boundaries. If you can't delegate, timebox them aggressively; 15 minutes for email twice a day, not 15 checks per hour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q4: Not Urgent + Not Important (Eliminate)&lt;/strong&gt;&lt;br&gt;
Excessive social media scrolling. Unnecessary meetings where you're CC'd "just in case." Reorganizing your desktop icons for the third time this week. Delete these from your day. They produce nothing and they consume the time you need for Q2 work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumkuxswg1dxlxo55kacd.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumkuxswg1dxlxo55kacd.webp" alt="Sticky notes on a planning board; tasks waiting to be sorted by what actually matters" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Q2 is where your career actually lives
&lt;/h2&gt;

&lt;p&gt;Here's the pattern I noticed in my 30-day audit. Every task that moved my career forward; shipping a feature, learning a new technology, writing a blog post, having a meaningful 1-on-1; was Q2. None of them were urgent when I started them. All of them were important.&lt;/p&gt;

&lt;p&gt;The tasks that consumed most of my time; answering Teams messages, attending status meetings, reviewing documents I wasn't the decision-maker on; were Q3. Urgent because someone was waiting. Unimportant because my absence wouldn't have changed the outcome.&lt;/p&gt;

&lt;p&gt;Research backs this up. A &lt;a href="https://www.mckinsey.com/capabilities/people-and-organizational-performance/our-insights/the-organization-blog/time-management-is-really-life-management" rel="noopener noreferrer"&gt;McKinsey study&lt;/a&gt; found that executives spend 28% of their day on email and another 19% on "gathering information." That's nearly half the workday on Q3 activities. The executives who outperform spend disproportionately more time on Q2: coaching, strategy, and capability building.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://calnewport.com/deep-work-rules-for-focused-success-in-a-distracted-world/" rel="noopener noreferrer"&gt;Cal Newport&lt;/a&gt; calls Q2 work "deep work" and argues it's the skill that separates people who build things from people who just stay busy. His framing is right: Q2 tasks require focused, uninterrupted blocks. You can't do strategic planning in the 4 minutes between Teams notifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The daily ritual I actually use
&lt;/h2&gt;

&lt;p&gt;After the 30-day audit, I settled on a system that takes about 5 minutes each morning:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Brain dump.&lt;/strong&gt; Write every task floating in your head into the &lt;a href="https://kitmul.com/en/agile-project-management/eisenhower-matrix" rel="noopener noreferrer"&gt;Eisenhower Matrix tool&lt;/a&gt;. Don't categorize yet; just get them out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sort by asking two questions.&lt;/strong&gt; For each task: "Does this have a real deadline?" (urgency) and "Will this matter in 30 days?" (importance). Drag it into the right quadrant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do Q1 first.&lt;/strong&gt; These are non-negotiable. But if Q1 has more than 3 items, something is wrong with your planning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block time for Q2.&lt;/strong&gt; I use the &lt;a href="https://kitmul.com/en/agile-project-management/pomodoro-agile" rel="noopener noreferrer"&gt;Pomodoro Timer&lt;/a&gt; for this; 25-minute focus blocks with no Teams, no email, no notifications. Two Pomodoro blocks per morning on Q2 work changed my output more than any other habit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch Q3.&lt;/strong&gt; Answer emails twice a day. Attend meetings only if you're the decision-maker. For recurring meetings, use the &lt;a href="https://kitmul.com/en/agile-project-management/meeting-cost-calculator" rel="noopener noreferrer"&gt;Meeting Cost Calculator&lt;/a&gt; once; when your team sees that the weekly sync costs $1,400 per session, they suddenly find ways to make it shorter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kill Q4.&lt;/strong&gt; If it's not urgent and not important, why is it on your list?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole process takes 5 minutes. The return is measured in hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eisenhower vs other prioritization frameworks
&lt;/h2&gt;

&lt;p&gt;The matrix isn't the only prioritization tool. Here's when to use what:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;th&gt;Weakness&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Eisenhower Matrix&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Daily/weekly personal task sorting&lt;/td&gt;
&lt;td&gt;Doesn't handle dependencies or team capacity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/wsjf-calculator"&gt;WSJF&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Backlog prioritization with 15+ items&lt;/td&gt;
&lt;td&gt;Overkill for personal task lists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/moscow-prioritization"&gt;MoSCoW&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scope negotiations with stakeholders&lt;/td&gt;
&lt;td&gt;Binary in/out; no nuance on ordering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/rice-scoring"&gt;RICE&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Product feature ranking&lt;/td&gt;
&lt;td&gt;Requires reach/impact data you might not have&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/kano-model"&gt;Kano Model&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Understanding customer delight vs basics&lt;/td&gt;
&lt;td&gt;Research-heavy; not for daily planning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Eisenhower Matrix works best for individual contributors and managers sorting their own week. If you need to prioritize a product backlog across a team, reach for &lt;a href="https://dev.to/en/agile-project-management/wsjf-calculator"&gt;WSJF&lt;/a&gt;. If you need to negotiate scope with a stakeholder, &lt;a href="https://dev.to/en/agile-project-management/moscow-prioritization"&gt;MoSCoW&lt;/a&gt; gives you a shared language. The tools solve different shapes of the same problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes I see
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Putting everything in Q1.&lt;/strong&gt; If everything is urgent and important, nothing is. You have a boundary problem, not a prioritization problem. Learn to say "I can do this Thursday" to things that arrive as "ASAP."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring Q2 because nothing is on fire.&lt;/strong&gt; Q2 tasks become Q1 tasks when you neglect them long enough. That "eventually upgrade the database" task? It's Q2 until the database crashes at 3 AM. Then it's Q1, it's expensive, and you're doing it under pressure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating Q3 as Q1.&lt;/strong&gt; Just because someone sent you an urgent email doesn't make the task important to &lt;em&gt;your&lt;/em&gt; goals. Other people's urgency is not your emergency. The fact that your boss asked for something today doesn't automatically make it important; it makes it urgent. These are different concepts, and confusing them is the single most common time management failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never reviewing the matrix.&lt;/strong&gt; Priorities change. A task that was Q2 on Monday might be Q1 by Wednesday because a deadline moved. Check your matrix every morning. It takes 2 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part nobody tells you about Eisenhower
&lt;/h2&gt;

&lt;p&gt;The popular version of the Eisenhower Matrix comes from &lt;a href="https://en.wikipedia.org/wiki/The_7_Habits_of_Highly_Effective_People" rel="noopener noreferrer"&gt;Stephen Covey's &lt;em&gt;The 7 Habits of Highly Effective People&lt;/em&gt;&lt;/a&gt;, published in 1989. But the idea predates the book. Eisenhower himself reportedly said: &lt;em&gt;"What is important is seldom urgent and what is urgent is seldom important."&lt;/em&gt; The &lt;a href="https://www.eisenhowerlibrary.gov/" rel="noopener noreferrer"&gt;Eisenhower Presidential Library&lt;/a&gt; attributes this to a 1954 speech, though the exact wording is debated.&lt;/p&gt;

&lt;p&gt;What's not debated is the principle. Eisenhower managed the complexity of the Cold War, the Interstate Highway System, and the creation of NASA while reportedly maintaining a calm, structured approach to his days. He wasn't productive because he worked more hours. He was productive because he worked on the right things.&lt;/p&gt;

&lt;p&gt;The matrix is his most lasting contribution to productivity thinking, and unlike most productivity frameworks from that era, it scales perfectly to modern work. Swap "phone calls" for "Teams messages" and "memos" for "emails"; the quadrants haven't changed in 70 years because the human tendency to confuse urgency with importance hasn't changed either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pair it with the right tools
&lt;/h2&gt;

&lt;p&gt;The Eisenhower Matrix handles the "what should I work on?" question. For the rest, pair it with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/pomodoro-agile"&gt;Pomodoro Timer&lt;/a&gt;&lt;/strong&gt; for executing Q1 and Q2 work in focused blocks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/standup-timer"&gt;Standup Timer&lt;/a&gt;&lt;/strong&gt; to keep daily standups short and Q3-efficient&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/okr-tracker"&gt;OKR Tracker&lt;/a&gt;&lt;/strong&gt; to define what "important" means at the quarterly level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/sprint-capacity-calculator"&gt;Sprint Capacity Calculator&lt;/a&gt;&lt;/strong&gt; to prevent overloading Q1 with more than your team can handle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/en/agile-project-management/scrum-poker"&gt;Scrum Poker&lt;/a&gt;&lt;/strong&gt; to size tasks before categorizing them&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/agile-project-management/eisenhower-matrix" rel="noopener noreferrer"&gt;Eisenhower Matrix&lt;/a&gt; runs in your browser. Drag tasks between quadrants. No account, no sync service, no data uploaded. Your task list stays on your device.&lt;/p&gt;

&lt;p&gt;Start with tomorrow morning. Write down every task. Sort them into four boxes. Then watch how much of your "urgent" work turns out to be noise.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The Eisenhower Matrix tool is free, private, and runs entirely in your browser. Part of the &lt;a href="https://dev.to/en/agile-project-management"&gt;Agile &amp;amp; Project Management toolkit&lt;/a&gt; on Kitmul.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I Stopped Using YouTube for Focus Music and My Pomodoro Sessions Got 10x Better</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Mon, 20 Apr 2026 18:58:46 +0000</pubDate>
      <link>https://dev.to/aralroca/i-stopped-using-youtube-for-focus-music-and-my-pomodoro-sessions-got-10x-better-2p82</link>
      <guid>https://dev.to/aralroca/i-stopped-using-youtube-for-focus-music-and-my-pomodoro-sessions-got-10x-better-2p82</guid>
      <description>&lt;p&gt;I run a Pomodoro timer every working day. Not because I read a productivity book. Because I kept losing 25-minute focus blocks to a YouTube ad for meal kits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ad problem nobody talks about
&lt;/h2&gt;

&lt;p&gt;The Pomodoro Technique is simple: 25 minutes of focused work, 5-minute break, repeat. &lt;a href="https://francescocirillo.com/products/the-pomodoro-technique" rel="noopener noreferrer"&gt;Francesco Cirillo&lt;/a&gt; designed it in the late 1980s with a tomato-shaped kitchen timer. No WiFi. No subscription. No interruptions from the tool itself.&lt;/p&gt;

&lt;p&gt;Fast forward to 2026. Most people who use background music during focus sessions stream it from YouTube, Spotify free tier, or some "lofi beats" livestream. The problem is obvious once you notice it: these platforms interrupt you with ads at random intervals. You're 18 minutes into a deep focus block, your brain has finally loaded the entire problem into working memory, and then a 15-second ad for car insurance yanks you out of &lt;a href="https://en.wikipedia.org/wiki/Flow_(psychology)" rel="noopener noreferrer"&gt;flow state&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The irony is brutal. You opened the music to &lt;em&gt;help&lt;/em&gt; you focus. The platform's business model requires &lt;em&gt;breaking&lt;/em&gt; your focus. These two goals are structurally incompatible unless you pay.&lt;/p&gt;

&lt;p&gt;And paying doesn't fully solve it either. Spotify's free tier has ads every few songs. YouTube Premium removes ads but still shows notification popups, recommendation sidebars, and autoplay previews that pull your eyes away from the code editor. The cognitive cost of even &lt;em&gt;seeing&lt;/em&gt; a notification is measurable; a &lt;a href="https://www.ics.uci.edu/~gmark/chi08-mark.pdf" rel="noopener noreferrer"&gt;University of California, Irvine study&lt;/a&gt; found it takes an average of 23 minutes to return to a task after an interruption.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built music into the timer
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/agile-project-management/pomodoro-agile" rel="noopener noreferrer"&gt;Pomodoro Timer&lt;/a&gt; on Kitmul ships with three built-in audio tracks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lofi Hip-Hop&lt;/strong&gt; (Work) ; 90 minutes of continuous, uninterrupted audio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jazz&lt;/strong&gt; (Read / Rest) ; 90 minutes, zero ads, zero interruptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beethoven&lt;/strong&gt; (Writing) ; 24 minutes of classical, perfect for a single Pomodoro cycle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxwje2zl47je39jx2okf.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxwje2zl47je39jx2okf.webp" alt="The Pomodoro Timer in focus mode; 25 minutes on the clock, no distractions in sight" width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tracks are served as static MP3 files from the same domain. No third-party player. No streaming SDK. No analytics pixel tracking what you listen to. Hit play, the audio starts, and it loops seamlessly until you stop the timer.&lt;/p&gt;

&lt;p&gt;Each mode (Focus, Short Break, Long Break) can have a different track assigned. I use Lofi for coding, Jazz for reading pull requests during breaks, and Beethoven when I'm writing documentation or blog posts like this one. The volume slider and track selection persist in localStorage, so your setup survives page refreshes.&lt;/p&gt;

&lt;p&gt;The audio starts at a random position in the track each session. This matters more than it sounds; if you hear the same opening bars 8 times a day, your brain stops treating it as background and starts &lt;em&gt;listening&lt;/em&gt; to it. Random start position keeps it ambient.&lt;/p&gt;

&lt;h2&gt;
  
  
  My daily setup
&lt;/h2&gt;

&lt;p&gt;I work in 4-Pomodoro blocks. Each block is roughly 2 hours: four 25-minute focus sessions with three 5-minute short breaks and one 15-minute long break at the end.&lt;/p&gt;

&lt;p&gt;A typical morning:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://kitmul.com/en/agile-project-management/pomodoro-agile" rel="noopener noreferrer"&gt;Pomodoro Timer&lt;/a&gt; in a pinned tab&lt;/li&gt;
&lt;li&gt;Set Focus to Lofi Hip-Hop, Short Break to Jazz&lt;/li&gt;
&lt;li&gt;Press play&lt;/li&gt;
&lt;li&gt;The browser tab title updates to show the countdown (&lt;code&gt;18:42 - Focus | Kitmul&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The favicon turns red during focus, green during breaks&lt;/li&gt;
&lt;li&gt;When the timer hits zero, a browser notification fires and the alarm sounds&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No context switch. No reaching for my phone. No opening another tab to find music. The entire workflow lives in one browser tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50j9tveo7m8siupls0eo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50j9tveo7m8siupls0eo.webp" alt="Settings panel showing background music selection per mode and volume control" width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The science behind music and focus
&lt;/h2&gt;

&lt;p&gt;Not all background audio helps concentration. Research from the &lt;a href="https://asa.scitation.org/journal/jas" rel="noopener noreferrer"&gt;Journal of the Acoustical Society of America&lt;/a&gt; shows that music with lyrics competes for the same cognitive resources as reading and writing. Instrumental music, particularly with consistent tempo and low complexity, actually &lt;em&gt;reduces&lt;/em&gt; perceived effort on repetitive tasks.&lt;/p&gt;

&lt;p&gt;The three tracks in the timer were chosen for this reason:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lofi&lt;/strong&gt;: steady beat, no vocals, 70-90 BPM ; sits in the sweet spot for sustained attention&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jazz&lt;/strong&gt;: slightly higher complexity, good for tasks that need creative lateral thinking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beethoven&lt;/strong&gt;: longer melodic phrases, works well for writing where you need sustained chains of thought&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't random. A &lt;a href="https://journals.sagepub.com/home/pom" rel="noopener noreferrer"&gt;meta-analysis published in Psychology of Music&lt;/a&gt; found that self-selected instrumental music at moderate volume improves performance on tasks requiring sustained attention by 5-15% compared to silence. The key word is &lt;em&gt;self-selected&lt;/em&gt;; the music works because you chose it, not because an algorithm decided it was time for a crypto ad.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Pomodoro Technique actually fixes
&lt;/h2&gt;

&lt;p&gt;The technique isn't really about tomatoes or 25-minute intervals. It's about two things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Time boxing.&lt;/strong&gt; You commit to working on &lt;em&gt;one thing&lt;/em&gt; for a defined period. This kills the "I'll just check Slack" impulse. If the timer is running, you're in focus mode. Period.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Forced breaks.&lt;/strong&gt; Most people skip breaks when they're "in the zone." This feels productive but leads to diminishing returns after 90 minutes. The Pomodoro break forces you to step back, which paradoxically keeps output higher across the full day.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Pomodoro_Technique" rel="noopener noreferrer"&gt;original technique&lt;/a&gt; recommends tracking completed Pomodoros to estimate future work. Our timer doesn't force this; it's a timer, not a project management tool. If you need sprint-level tracking, pair it with the &lt;a href="https://dev.to/en/agile-project-management/wip-aging-chart"&gt;WIP Aging Chart&lt;/a&gt; or the &lt;a href="https://dev.to/en/agile-project-management/monte-carlo-forecasting"&gt;Monte Carlo Forecasting tool&lt;/a&gt; to get statistical delivery predictions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing to alternatives
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Kitmul Pomodoro&lt;/th&gt;
&lt;th&gt;YouTube + Timer App&lt;/th&gt;
&lt;th&gt;Spotify + Timer App&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Built-in music&lt;/td&gt;
&lt;td&gt;3 curated tracks&lt;/td&gt;
&lt;td&gt;Requires separate tab&lt;/td&gt;
&lt;td&gt;Requires separate app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ads during focus&lt;/td&gt;
&lt;td&gt;None, ever&lt;/td&gt;
&lt;td&gt;Every 5-15 min (free)&lt;/td&gt;
&lt;td&gt;Every 3-6 songs (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy&lt;/td&gt;
&lt;td&gt;No data sent anywhere&lt;/td&gt;
&lt;td&gt;Google tracking&lt;/td&gt;
&lt;td&gt;Spotify tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works offline&lt;/td&gt;
&lt;td&gt;Yes (PWA)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tab title countdown&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Favicon changes by mode&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free with ads / $14/mo&lt;/td&gt;
&lt;td&gt;Free with ads / $11/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The "free with ads" model makes sense for entertainment. It makes zero sense for a productivity tool. An ad during a movie is annoying. An ad during a focus session is &lt;em&gt;destructive&lt;/em&gt;. The interruption cost far exceeds the 15 seconds the ad occupies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips for getting the most out of it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pin the tab.&lt;/strong&gt; A pinned tab shows only the favicon, which changes color by mode (red = focus, green = short break, blue = long break). You get a visual status indicator without dedicating screen space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable browser notifications.&lt;/strong&gt; The timer fires a desktop notification when each session ends. This means you can work in your IDE or terminal without watching the timer tab. Request notification permission once and forget about it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adjust durations.&lt;/strong&gt; The default 25/5/15 works for most people, but some tasks need longer focus blocks. The sliders let you set Focus anywhere from 1 to 60 minutes. I use 45-minute blocks for writing and 25-minute blocks for coding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use the &lt;a href="https://dev.to/en/datetime/countdown-timer"&gt;Countdown Timer&lt;/a&gt; for non-Pomodoro time boxing.&lt;/strong&gt; Not everything fits the Pomodoro structure. If you need a one-off 12-minute timer for a standup or a &lt;a href="https://dev.to/en/agile-project-management/meeting-cost-calculator"&gt;meeting agenda&lt;/a&gt;, the countdown timer is simpler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pair with the &lt;a href="https://dev.to/en/health/caffeine-half-life-calculator"&gt;Caffeine Calculator&lt;/a&gt;.&lt;/strong&gt; If you're stacking Pomodoro blocks through the afternoon, know when to stop drinking coffee. Caffeine has a &lt;a href="https://en.wikipedia.org/wiki/Caffeine#Pharmacology" rel="noopener noreferrer"&gt;half-life of about 5 hours&lt;/a&gt;; a 3 PM espresso is still half-present at 8 PM.&lt;/p&gt;

&lt;h2&gt;
  
  
  It runs in your browser. That's the point.
&lt;/h2&gt;

&lt;p&gt;No download. No Electron app eating 400MB of RAM. No account. No sync service. No "upgrade to Pro for custom sounds."&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/agile-project-management/pomodoro-agile" rel="noopener noreferrer"&gt;Pomodoro Timer&lt;/a&gt; is a single browser tab that does one thing well: it counts down, plays music, and stays out of your way. Everything runs client-side. Your timer settings, music preferences, and volume level stay in localStorage on your device.&lt;/p&gt;

&lt;p&gt;If you're currently using YouTube or Spotify as your focus music source, try switching to built-in audio for one day. Count how many times you get interrupted. The number will probably be zero. That's the point.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The Pomodoro Timer is free, private, and works offline as a PWA. No signup, no ads, no data leaves your browser. Part of the &lt;a href="https://dev.to/en/agile-project-management"&gt;Agile &amp;amp; Project Management toolkit&lt;/a&gt; on Kitmul.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>SAP Hybris Impex When None of Us on the Team Can Read It</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Sat, 18 Apr 2026 15:31:01 +0000</pubDate>
      <link>https://dev.to/aralroca/sap-hybris-impex-when-none-of-us-on-the-team-can-read-it-4ok</link>
      <guid>https://dev.to/aralroca/sap-hybris-impex-when-none-of-us-on-the-team-can-read-it-4ok</guid>
      <description>&lt;p&gt;I'm currently embedded as an external on a team that uses the &lt;a href="https://help.sap.com/docs/SAP_COMMERCE" rel="noopener noreferrer"&gt;Hybris Management Console&lt;/a&gt; — HMC for short — to administer a SAP Commerce environment. Every few days the shared environment gets refreshed from production, which is exactly what you want for most of the data, and exactly what you don't want for half-finished configuration that hasn't made it to prod yet. A content type you registered on Tuesday, a workflow tweak from Wednesday, a test user you needed for a demo — gone by Friday morning. Everyone on the team has been through this loop enough times that they've stopped being surprised.&lt;/p&gt;

&lt;p&gt;Impex is the natural answer. If you can describe a configuration change as an Impex file, you can replay it after every refresh, commit it to the repo, code-review it, and treat it like the rest of the platform. That is the official playbook and it is the right one.&lt;/p&gt;

&lt;p&gt;The problem is more human than technical. Nobody on the team reads Impex fluently. The format predates most of the languages the team writes every day, the tooling around it is sparse, and a pull request that is sixty lines of semicolon-separated text doesn't exactly invite careful review. So people would rather click through the HMC, accept that the work will evaporate in a few days, and move on. Knowing this fixes itself with tooling, not with a training session, I spent a week building the eight browser tools this post is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Impex is, in one paragraph
&lt;/h2&gt;

&lt;p&gt;Impex is a plain-text scripting format SAP Commerce uses to insert, update, or remove rows in the platform's type system. Every Hybris object — &lt;code&gt;Product&lt;/code&gt;, &lt;code&gt;Catalog&lt;/code&gt;, &lt;code&gt;Category&lt;/code&gt;, &lt;code&gt;PriceRow&lt;/code&gt;, &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Customer&lt;/code&gt;, &lt;code&gt;Order&lt;/code&gt; — is a Java-defined type, and Impex is how you push data at those types without writing Java. A file is a sequence of "blocks," each with a header line declaring a mode and type (&lt;code&gt;INSERT_UPDATE Product;code[unique=true];name&lt;/code&gt;) followed by semicolon-separated data rows (&lt;code&gt;;P-0001;My Product&lt;/code&gt;). Comments start with &lt;code&gt;#&lt;/code&gt;. Macros start with &lt;code&gt;$&lt;/code&gt;. Qualifier paths go inside parentheses: &lt;code&gt;catalogVersion(catalog(id),version)&lt;/code&gt;. The official &lt;a href="https://help.sap.com/docs/SAP_COMMERCE/d0224eca81e249cb821f2cdf45a82ace/1c8f5bebdc6e434782ff0cfdb0ca1847.html" rel="noopener noreferrer"&gt;Impex interpreter reference&lt;/a&gt; is the authoritative spec.&lt;/p&gt;

&lt;p&gt;That is the entire language. It is genuinely small. What makes it hard to read is not the grammar; it's that it's a tabular format displayed in a text editor, without column alignment, without syntax highlighting, without any of the affordances you'd want for reviewing a spreadsheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why HMC plus a periodic refresh forces this conversation
&lt;/h2&gt;

&lt;p&gt;There is a recurring pattern in SAP Commerce projects: you have one production-like environment shared across product, QA, and engineering. To keep it close to reality, someone runs a refresh from production on a schedule — weekly, bi-weekly, overnight. That refresh is non-negotiable; it's how bugs get reproduced. But it means every configuration change that lives only in HMC has a half-life.&lt;/p&gt;

&lt;p&gt;There are three ways out and only one of them scales.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option one:&lt;/strong&gt; stop doing the refresh. You immediately drift from production, QA starts missing real bugs, the refresh comes back, and you've lost a month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option two:&lt;/strong&gt; ask people not to click in HMC. This is a social contract that lasts about a sprint. The tool is there, it works, deadlines exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option three:&lt;/strong&gt; every change goes into version control as an Impex file and is replayed after each refresh. This is the answer the platform has always wanted you to pick. It's also the one that requires your team to be comfortable reading and writing Impex, which brings me back to the opening of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  The eight tools
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmxosodyjzq5of2t3l2x.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmxosodyjzq5of2t3l2x.webp" alt="Retail catalog shelves; Impex is the plumbing behind every product tile you see in a SAP Commerce storefront" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything below runs locally in your browser. Nothing is uploaded. The parser is a ~550-line TypeScript module that handles quoted fields, escaped semicolons, line continuations, macros, modifier blocks, and multi-block files. If you find real-world Impex this parser can't handle, I'd like to see it.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/en/data/impex-table-editor"&gt;Impex Table Editor&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is the one that does the heavy lifting on my team. Paste a block, get a spreadsheet-style grid, edit cells inline, add or remove rows, copy the regenerated Impex back out. When the person writing the change doesn't read Impex but does read Excel, this is the bridge. It is also the tool I reach for first when I need to make a ten-row change without scrolling through semicolons.&lt;/p&gt;

&lt;p&gt;If nothing else in this post sticks, the table editor is the one to bookmark.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/en/data/impex-to-csv"&gt;Impex to CSV Converter&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Turns any Impex block into CSV, one header per column. Useful when someone from content wants to see the current state of a catalog section in a spreadsheet without waiting for an engineer.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/en/data/csv-to-impex"&gt;CSV to Impex Converter&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The reverse: a CSV (often pasted from Google Sheets) becomes an Impex script, with the type name and unique column selected explicitly. Product people can draft the change in Sheets, the engineer converts it and commits. The review diff stays reviewable.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/en/data/impex-to-json"&gt;Impex to JSON&lt;/a&gt; and &lt;a href="https://dev.to/en/data/json-to-impex"&gt;JSON to Impex&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;JSON is the lingua franca of everything that isn't Impex. If you're scripting a migration, generating Impex from a source of truth, or diffing two versions, a structured representation is easier than regexing semicolons. Each block becomes &lt;code&gt;{mode, type, headers, rows}&lt;/code&gt;, macros are first-class, and the two tools round-trip so you can edit the JSON and convert back. A swap button at the top of each page flips the direction.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/en/data/impex-validator"&gt;Impex Validator / Linter&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Reports missing type names, unknown modifiers, duplicate unique keys across data rows, undefined macros, and column-count mismatches. None of these are exotic errors — they are all things SAP's interpreter will accept and then silently produce a bad import for. Adding this as a CI check on &lt;code&gt;.impex&lt;/code&gt; files is the single highest-leverage change a team using Impex in version control can make.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/en/data/impex-macro-expander"&gt;Impex Macro Expander&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given an Impex file with &lt;code&gt;$macros&lt;/code&gt;, produces the same file with every reference inlined. Fixed-point expansion, so macros that reference macros resolve cleanly. This is what you commit into an audit artefact. Auditors are not going to chase &lt;code&gt;$macros&lt;/code&gt; through your repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://dev.to/en/data/impex-to-sql"&gt;Impex to SQL (Approximate)&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hybris abstracts over the database. Sometimes that abstraction leaks — a DBA asks what's actually being written, or you're reasoning about performance. This tool flattens Impex into approximate INSERT / UPDATE / DELETE in Postgres, MySQL, or ANSI-standard SQL, with &lt;code&gt;INSERT_UPDATE&lt;/code&gt; rendered as &lt;code&gt;ON CONFLICT&lt;/code&gt; / &lt;code&gt;ON DUPLICATE KEY&lt;/code&gt; / &lt;code&gt;MERGE&lt;/code&gt; depending on dialect. It is explicitly approximate; qualifier paths like &lt;code&gt;catalogVersion(catalog(id),version)&lt;/code&gt; can't be rendered faithfully as joins without your &lt;code&gt;items.xml&lt;/code&gt;. But for a mental model conversation, it's faster than spinning up a local Hybris and watching the query log.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcs60kkyo0fngvpv10i5s.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcs60kkyo0fngvpv10i5s.webp" alt="A developer's laptop showing terminal output; most Impex work happens at the boundary between code and the platform console" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The workflow I'm pushing on my team
&lt;/h2&gt;

&lt;p&gt;Short version, ordered by ROI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impex goes both ways: dump what you did in HMC into a &lt;code&gt;.impex&lt;/code&gt; file, or edit &lt;code&gt;.impex&lt;/code&gt; and import to skip HMC entirely.&lt;/strong&gt; HMC is slow for configuration — a twenty-field form is tedious the third time you touch it. For anything repetitive or bulk, writing the Impex directly and running the import is several times faster than clicking. And whatever you did have to do in HMC gets exported to &lt;code&gt;.impex&lt;/code&gt; so it survives the next refresh.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-trivial edits happen in the &lt;a href="https://dev.to/en/data/impex-table-editor"&gt;Table Editor&lt;/a&gt;.&lt;/strong&gt; Flat-editor Impex is fine for adding one column or flipping a flag. For anything with more than a handful of rows, the table editor is correct and the flat editor is not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run the &lt;a href="https://dev.to/en/data/impex-validator"&gt;Impex Validator&lt;/a&gt; before every import.&lt;/strong&gt; This is 90% of the value of the tooling in this post. It catches duplicate unique keys, unknown modifiers, and undefined macros before SAP's interpreter silently accepts them and produces a bad import. Right now we pass it by hand over each &lt;code&gt;.impex&lt;/code&gt; before running the import; not automated, but it catches most of the surprises.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diffs are done on JSON.&lt;/strong&gt; Convert both versions of a file to JSON via &lt;a href="https://dev.to/en/data/impex-to-json"&gt;Impex to JSON&lt;/a&gt; and diff that. Row-level semicolon diffs are unreadable; structured diffs are not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Macros are expanded in audit artefacts.&lt;/strong&gt; Commit the compact form. When compliance asks what the deployment actually did, hand them the expanded version.&lt;/p&gt;

&lt;h2&gt;
  
  
  What still bites
&lt;/h2&gt;

&lt;p&gt;Not every Impex problem has a browser-tool answer.&lt;/p&gt;

&lt;p&gt;Type-system evolution is the big one. When somebody renames a field in &lt;code&gt;items.xml&lt;/code&gt;, every Impex file referencing the old name silently starts writing to the wrong column or failing in confusing ways. No linter in the browser can catch this without access to your specific type definitions. A small project-local script that walks your &lt;code&gt;.impex&lt;/code&gt; files and cross-references attributes against the current type system is worth a weekend. I haven't shipped one because every team has a different setup.&lt;/p&gt;

&lt;p&gt;Performance is the other. Large Impex imports behave differently from bulk SQL loads — the interpreter validates every row, triggers platform events, and invalidates caches. If a million-row import takes six hours, the fix is almost never "tune the database." It's "split the file and import in parallel" or "disable cache eviction during the load." The &lt;a href="https://help.sap.com/docs/SAP_COMMERCE" rel="noopener noreferrer"&gt;SAP Commerce performance documentation&lt;/a&gt; covers this well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built this and not something else
&lt;/h2&gt;

&lt;p&gt;The honest answer: my team (myself included) was not going to learn to read Impex by reading more Impex. Documentation didn't fix it. Pair programming didn't fix it. The bet was that handing someone a &lt;a href="https://dev.to/en/data/impex-table-editor"&gt;spreadsheet UI&lt;/a&gt; over an Impex block and saying "edit this like you'd edit anything else, the tool will write the Impex for you" might lower the barrier enough for Impex to become a format the team treats like CSV — a transport representation that happens to be how SAP Commerce wants the data, not a language they need to master.&lt;/p&gt;

&lt;h2&gt;
  
  
  Will this actually work? I don't know yet.
&lt;/h2&gt;

&lt;p&gt;I want to be straight about where I am with this. These tools exist because my team is trying to answer a bigger question: &lt;strong&gt;can configuration-as-code via Impex replace clicking through HMC, long-term, for a team that isn't fluent in Impex?&lt;/strong&gt; The tools are a bet on "yes." They are not proof.&lt;/p&gt;

&lt;p&gt;There are a few ways this experiment could fall apart. Maybe the table editor is fine for 80% of edits but the remaining 20% — the ones involving nested qualifier paths, macros that reference other catalogs, modifier subtleties — still push people back to HMC and the discipline erodes. Maybe writing Impex is the easy part and the hard part is the CI pipeline that actually replays the scripts after a refresh, which is not what this post is about. Maybe the type system evolves faster than the tooling can keep up and the validator starts producing noise people learn to ignore. Any of these would mean "infrastructure-as-code in HMC via Impex" isn't really the right framing, and we need a different abstraction.&lt;/p&gt;

&lt;p&gt;I'll write a follow-up in a few months once there's real data. Either these tools become the default path and configuration-as-code works the way SAP always wanted it to, or we learn something interesting about why it doesn't, and that's its own post. I don't have a strong prior either way.&lt;/p&gt;

&lt;p&gt;If you're running SAP Commerce with the same HMC + refresh setup and you want to try something similar, the tools are free, local, and will keep working regardless of what I conclude. Bookmark the ones that fit your workflow. If you end up with your own data — positive or negative — I'd like to hear it.&lt;/p&gt;

&lt;p&gt;For the ecosystem context: the &lt;a href="https://help.sap.com/docs/SAP_COMMERCE/d0224eca81e249cb821f2cdf45a82ace/1c8f5bebdc6e434782ff0cfdb0ca1847.html" rel="noopener noreferrer"&gt;SAP Help ImpEx documentation&lt;/a&gt; is the canonical reference, the &lt;a href="https://community.sap.com/topics/commerce-cloud" rel="noopener noreferrer"&gt;SAP Commerce community forums&lt;/a&gt; are better than Stack Overflow for version-specific questions, and the &lt;a href="https://www.gartner.com/en/documents/magic-quadrant-for-digital-commerce" rel="noopener noreferrer"&gt;Gartner Magic Quadrant for Digital Commerce&lt;/a&gt; covers where SAP Commerce sits in the broader enterprise ecommerce landscape.&lt;/p&gt;

&lt;p&gt;More in a few months.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Was Paying Anthropic to Read CSS Class Names</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Fri, 17 Apr 2026 14:04:33 +0000</pubDate>
      <link>https://dev.to/aralroca/i-was-paying-anthropic-to-read-css-class-names-o2c</link>
      <guid>https://dev.to/aralroca/i-was-paying-anthropic-to-read-css-class-names-o2c</guid>
      <description>&lt;p&gt;I burned through 176 million Anthropic tokens last Wednesday. You can see the spike in the screenshot further down. Most of that was productive Claude Code work, but when I tracked down the anomaly I found a batch job quietly shovelling raw HTML into Claude Sonnet 4.5 for summarization. The prompts worked; the token budget did not. When I finally looked at what my scraper was feeding the model, roughly 70% of every request was &lt;code&gt;&amp;lt;div class="css-1f2x"&amp;gt;&lt;/code&gt; soup. The actual article, the part I cared about, was maybe 25% of the payload.&lt;/p&gt;

&lt;p&gt;The fix was a five-line change: convert HTML to Markdown before sending it to the model. Token count dropped by 60%. Same output quality. I wish I had learned this sooner.&lt;/p&gt;

&lt;p&gt;This post is about why that works, when it matters, and a few adjacent problems that same trick solves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why HTML is a token disaster
&lt;/h2&gt;

&lt;p&gt;LLMs tokenize text. Anthropic exposes a &lt;a href="https://docs.claude.com/en/docs/build-with-claude/token-counting" rel="noopener noreferrer"&gt;token counting endpoint&lt;/a&gt; in the Claude API, and OpenAI's open-source &lt;a href="https://github.com/openai/tiktoken" rel="noopener noreferrer"&gt;tiktoken&lt;/a&gt; gives a similar view: most English prose splits into roughly one token per 3-4 characters. But HTML is not prose. It is a nested tree of tags, class names, inline styles, SVG attributes, and JSON blobs dumped into &lt;code&gt;data-*&lt;/code&gt; attributes by every modern framework.&lt;/p&gt;

&lt;p&gt;You can verify this yourself. Paste a paragraph of plain text into Anthropic's token counter and note the count. Then wrap it in a typical React-generated &lt;code&gt;&amp;lt;div class="prose dark:prose-invert max-w-none sm:px-6 lg:px-8"&amp;gt;&lt;/code&gt; and count again. The wrapper alone, that one line, can cost you 30-40 tokens. Multiply that across a scraped page with 500 nested divs and you see where the money goes.&lt;/p&gt;

&lt;p&gt;Markdown, by contrast, is nearly invisible to a tokenizer. A heading is two characters: &lt;code&gt;#&lt;/code&gt;. A bold span is four: &lt;code&gt;**x**&lt;/code&gt;. A link is &lt;code&gt;[text](url)&lt;/code&gt;, and the model handles it natively because its training corpus is saturated with Markdown from GitHub, Stack Overflow, and Reddit.&lt;/p&gt;

&lt;p&gt;I ran a quick test on the Wikipedia article for the &lt;a href="https://en.wikipedia.org/wiki/HTTP" rel="noopener noreferrer"&gt;HTTP protocol&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Raw HTML (saved from browser): ~48,000 tokens&lt;/li&gt;
&lt;li&gt;Cleaned HTML (boilerpipe style): ~22,000 tokens&lt;/li&gt;
&lt;li&gt;Markdown conversion: ~8,900 tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is an 81% reduction against raw, and 60% against even a cleaned HTML payload. On a model that charges per input token, this is not a micro-optimization. It is the difference between a viable product and a Stripe chargeback.&lt;/p&gt;

&lt;p&gt;Here is a week of my actual Claude Code usage for reference. Four days, 433 million tokens, about $306 at list prices (I am on a Max subscription, but the equivalent pay-as-you-go cost makes the scale legible). Most of that is productive coding. Imagine what shaving 10-15% off by not shipping structural noise would buy you over a year.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46uuu2geuu8nvc292feq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46uuu2geuu8nvc292feq.webp" alt="Claude Code token usage this week; 433M tokens across four days, roughly $306 in equivalent API cost" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The RAG pipeline case
&lt;/h2&gt;

&lt;p&gt;If you are building retrieval-augmented generation, this matters even more. A RAG system typically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crawls or scrapes source documents&lt;/li&gt;
&lt;li&gt;Chunks them into pieces that fit the embedding model's context window&lt;/li&gt;
&lt;li&gt;Embeds each chunk into a vector database&lt;/li&gt;
&lt;li&gt;At query time, retrieves the top-K chunks and injects them into the LLM prompt&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of those steps gets worse with HTML in the loop. Embeddings drift because the model is trying to encode CSS class names alongside actual meaning. Chunking gets jagged; you either split mid-tag and confuse the retriever, or you use a naive character split that cuts a sentence in half. Retrieval latency grows because the vector space is polluted with structural noise.&lt;/p&gt;

&lt;p&gt;Converting to Markdown before chunking solves all three. The excellent &lt;a href="https://python.langchain.com/docs/concepts/text_splitters/" rel="noopener noreferrer"&gt;LangChain docs&lt;/a&gt; quietly recommend this: use &lt;code&gt;MarkdownHeaderTextSplitter&lt;/code&gt; or &lt;code&gt;RecursiveCharacterTextSplitter&lt;/code&gt; with Markdown separators. Their own examples strip HTML to Markdown first. There is a reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you cannot run Python on a server
&lt;/h2&gt;

&lt;p&gt;A lot of the HTML-to-Markdown literature assumes you have a backend with &lt;a href="https://www.crummy.com/software/BeautifulSoup/" rel="noopener noreferrer"&gt;BeautifulSoup&lt;/a&gt; and &lt;a href="https://github.com/matthewwpeters/markdownify" rel="noopener noreferrer"&gt;markdownify&lt;/a&gt; installed. That is fine if you are building a pipeline. It is painful if you are a content writer, a journalist archiving sources, or a developer doing a one-off migration at 11pm.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://kitmul.com/en/writing/html-to-markdown" rel="noopener noreferrer"&gt;Kitmul HTML to Markdown&lt;/a&gt; because I kept reaching for that exact workflow and hating every option. The tool runs in the browser. Paste the HTML source, get the Markdown. Nothing uploads, nothing phones home. The conversion happens with JavaScript on your machine, which means you can paste internal wiki exports, legal drafts, or client content without a second thought.&lt;/p&gt;

&lt;p&gt;If you have never inspected the HTML behind a page, open any article, right-click, choose "View Page Source", and copy the article body. Feed that into the tool. What comes back is something you can actually put into a prompt, paste into Notion, or commit to a Git repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seven places this actually helps
&lt;/h2&gt;

&lt;p&gt;It took me a while to recognize how many of my problems reduce to "I have HTML and I wish it were Markdown". A partial list:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feeding a long article to an LLM.&lt;/strong&gt; The single largest wins happen when you are summarizing, extracting entities, or asking questions about a long web page. Markdown strips out the chrome and leaves the substance. Prompt cost drops, and ironically the model does better on the cleaner input because it stops getting distracted by CSS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Migrating a blog off WordPress or Ghost.&lt;/strong&gt; If you are moving to a static site generator like &lt;a href="https://astro.build/" rel="noopener noreferrer"&gt;Astro&lt;/a&gt;, &lt;a href="https://gohugo.io/" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt;, or Jekyll, every post needs to be a &lt;code&gt;.md&lt;/code&gt; file. Export your WordPress XML, feed each &lt;code&gt;&amp;lt;content:encoded&amp;gt;&lt;/code&gt; block through the converter, drop the result into &lt;code&gt;content/posts/&lt;/code&gt;. I moved 84 posts this way in an evening.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Archiving research.&lt;/strong&gt; I keep a personal wiki of engineering articles I reference often. Pages disappear from the web all the time; &lt;a href="https://www.nature.com/articles/d41586-024-01095-4" rel="noopener noreferrer"&gt;the average web page lifespan is under 100 days&lt;/a&gt;. Markdown snapshots take milliseconds to read, diff cleanly in Git, and survive format churn in a way screenshots or PDFs do not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preparing training data or few-shot examples.&lt;/strong&gt; If you are curating examples for fine-tuning or in-context learning, you want them consistent. Markdown is the consistent form. Every scraped source ends up the same shape, with the same heading hierarchy, and no random &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; wrappers confusing your template.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cleaning up content after visual editors.&lt;/strong&gt; Tools like Notion, Medium, or CKEditor export HTML that is technically correct but full of &lt;code&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;em&amp;gt;&amp;lt;u&amp;gt;&lt;/code&gt; nesting nobody wants. Round-tripping through Markdown collapses that to the minimum semantic form, and you get a diffable, portable source of truth out of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Writing documentation from scraped API references.&lt;/strong&gt; I have done this for three SDKs now. Grab the rendered HTML from the vendor's docs (many are built with MkDocs or Docusaurus and have no Markdown source available), convert it, and you have a starting point you can edit and commit. It is faster than copy-pasting each code block by hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reducing costs on the &lt;a href="https://docs.claude.com/en/home" rel="noopener noreferrer"&gt;Claude API&lt;/a&gt; and &lt;a href="https://ai.google.dev/" rel="noopener noreferrer"&gt;Gemini API&lt;/a&gt;.&lt;/strong&gt; Every frontier model bills input tokens. Anthropic's &lt;a href="https://docs.claude.com/en/docs/build-with-claude/prompt-caching" rel="noopener noreferrer"&gt;prompt caching&lt;/a&gt; helps, but caching 48K of HTML is still worse than caching 9K of Markdown. Caches also evict. The cheapest token is the one you never send.&lt;/p&gt;

&lt;h2&gt;
  
  
  What gets lost in the conversion
&lt;/h2&gt;

&lt;p&gt;Be honest about the trade-offs. A few things do not survive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visual styling.&lt;/strong&gt; Colors, fonts, custom CSS. If the visual layout is the content (infographics, landing pages), Markdown is the wrong target.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive components.&lt;/strong&gt; Embedded forms, iframes, JavaScript widgets. These become either plain links or they disappear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exact table layouts.&lt;/strong&gt; Markdown tables handle rows and columns, but merged cells, colspans, and nested tables simplify or break. For data-heavy tables, CSV export is usually a better path; our &lt;a href="https://kitmul.com/en/data-converters/csv-to-json" rel="noopener noreferrer"&gt;CSV to JSON tool&lt;/a&gt; covers the adjacent case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image positioning.&lt;/strong&gt; Markdown images are inline, top-down. Float layouts do not translate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For 90% of text-driven web pages, none of this matters. For the remaining 10%, you probably want the HTML anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  A concrete workflow
&lt;/h2&gt;

&lt;p&gt;Here is the routine I have settled into for LLM work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scrape the page with &lt;code&gt;fetch&lt;/code&gt; or &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; and grab the innerHTML of the article body, not the full document. A decent CSS selector does half the cleanup for you.&lt;/li&gt;
&lt;li&gt;If it is a one-off, paste into the &lt;a href="https://kitmul.com/en/writing/html-to-markdown" rel="noopener noreferrer"&gt;HTML to Markdown converter&lt;/a&gt;. If it is a batch, use a library like &lt;code&gt;turndown&lt;/code&gt; (&lt;a href="https://github.com/mixmark-io/turndown" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;) or &lt;code&gt;markdownify&lt;/code&gt; in Python.&lt;/li&gt;
&lt;li&gt;Strip boilerplate (cookie banners, "related posts", newsletter CTAs). Markdown makes this easy: the noise tends to cluster at the top and bottom.&lt;/li&gt;
&lt;li&gt;Feed to the model. For long documents, chunk along Markdown headings rather than character counts.&lt;/li&gt;
&lt;li&gt;Cache the Markdown version locally. The next run should not repeat step 1.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole thing usually takes longer to describe than to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The broader point
&lt;/h2&gt;

&lt;p&gt;Format conversion sounds boring. It is, until you watch your API bill shrink by 60% because you stopped sending structural ASCII noise to a trillion-parameter model. LLMs are expensive not in absolute terms but per million tokens, and the number of pipelines where someone is shipping raw HTML into a context window is genuinely embarrassing.&lt;/p&gt;

&lt;p&gt;Markdown is the lingua franca of AI training data. That is a fact about the world, not an opinion. Working in Markdown aligns your inputs with what the model was trained to handle, and a plain-text intermediate form also gives you a version your Git history can meaningfully diff, which is something you will be grateful for in six months when you are trying to remember what the prompt looked like in Q3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Open the &lt;a href="https://kitmul.com/en/writing/html-to-markdown" rel="noopener noreferrer"&gt;HTML to Markdown converter&lt;/a&gt;, paste any HTML, and see the token count drop. Everything runs in your browser, which means your client drafts, scraped sources, and internal docs never leave your machine. The code is inspectable in the DevTools network tab; there are zero outbound requests during conversion.&lt;/p&gt;

&lt;p&gt;If you want to publish the Markdown somewhere visual, the &lt;a href="https://kitmul.com/en/writing/markdown-to-medium" rel="noopener noreferrer"&gt;Markdown to Medium converter&lt;/a&gt; handles publication-ready output for Medium's editor.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Related reading: &lt;a href="https://kitmul.com/en/blog/markdown-to-medium-guide" rel="noopener noreferrer"&gt;How to Publish Markdown to Medium Without Losing Formatting&lt;/a&gt; · &lt;a href="https://kitmul.com/en/blog/why-client-side-tools-are-more-private" rel="noopener noreferrer"&gt;Why Client-Side Tools Are More Private Than the Cloud&lt;/a&gt; · &lt;a href="https://kitmul.com/en/blog/avif-image-format-complete-guide" rel="noopener noreferrer"&gt;AVIF in 2026: The Complete Guide&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Related tools: &lt;a href="https://kitmul.com/en/developer/json-formatter" rel="noopener noreferrer"&gt;JSON Formatter&lt;/a&gt; · &lt;a href="https://kitmul.com/en/data-converters/csv-to-json" rel="noopener noreferrer"&gt;CSV to JSON&lt;/a&gt; · &lt;a href="https://kitmul.com/en/writing/word-counter" rel="noopener noreferrer"&gt;Word Counter&lt;/a&gt; · &lt;a href="https://kitmul.com/en/writing/text-diff" rel="noopener noreferrer"&gt;Text Diff Checker&lt;/a&gt; · &lt;a href="https://kitmul.com/en/image-design/image-compressor" rel="noopener noreferrer"&gt;Image Compressor&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>markdown</category>
      <category>webdev</category>
      <category>llm</category>
      <category>ai</category>
    </item>
    <item>
      <title>WSJF, Cost of Delay and Why Your Loudest Stakeholder Keeps Winning the Backlog Argument</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Thu, 16 Apr 2026 19:53:48 +0000</pubDate>
      <link>https://dev.to/aralroca/wsjf-cost-of-delay-and-why-your-loudest-stakeholder-keeps-winning-the-backlog-argument-2ggf</link>
      <guid>https://dev.to/aralroca/wsjf-cost-of-delay-and-why-your-loudest-stakeholder-keeps-winning-the-backlog-argument-2ggf</guid>
      <description>&lt;p&gt;A few months ago I sat in a PI planning session where a team of twelve argued for forty minutes about whether a "see product alternatives" button was more important than a "notify me" button for out-of-stock items. Both PMs had slide decks. Both had data. Both were convinced. The conversation ended the way those conversations always end; the loudest person in the room won, and everyone else went back to their laptops with a quiet grudge.&lt;/p&gt;

&lt;p&gt;That meeting is why I rebuilt our &lt;a href="https://kitmul.com/en/agile-project-management/wsjf-calculator" rel="noopener noreferrer"&gt;WSJF Calculator&lt;/a&gt;. Not because the world needed yet another backlog prioritization tool, but because I kept watching smart teams flush an entire quarter down the drain arguing about feelings when the math has existed since the 1980s.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trick nobody tells you about prioritization
&lt;/h2&gt;

&lt;p&gt;Most people think prioritization is about picking the most valuable thing. It isn't. It's about picking the thing where &lt;strong&gt;value divided by size&lt;/strong&gt; is highest. That distinction sounds pedantic until you realize it's the difference between shipping eight small wins in a quarter and shipping one lumbering "strategic initiative" that nobody really wanted.&lt;/p&gt;

&lt;p&gt;That's the whole thesis behind &lt;a href="https://scaledagileframework.com/wsjf/" rel="noopener noreferrer"&gt;Weighted Shortest Job First&lt;/a&gt;. You score each backlog item on two things; how expensive it is to &lt;em&gt;delay&lt;/em&gt;, and how big the job is. Then you divide. The highest score wins. That's it. No story point debates at 9am on a Monday, no "is login page a 3 or a 5", no pretending your gut feeling is a methodology.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WSJF = Cost of Delay / Job Size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.productplan.com/glossary/weighted-shortest-job-first/" rel="noopener noreferrer"&gt;Don Reinertsen&lt;/a&gt; popularized this in &lt;em&gt;The Principles of Product Development Flow&lt;/em&gt;, which I'd call the best agile book ever written if the phrase "agile book" didn't immediately make most engineers reach for the nearest window. It's actually a &lt;a href="https://en.wikipedia.org/wiki/Queueing_theory" rel="noopener noreferrer"&gt;queueing theory&lt;/a&gt; book dressed up as a management book, which is why it's so good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost of Delay is three things, not one
&lt;/h2&gt;

&lt;p&gt;Here's where most WSJF spreadsheets get it wrong. &lt;a href="https://en.wikipedia.org/wiki/Cost_of_delay" rel="noopener noreferrer"&gt;Cost of Delay&lt;/a&gt; isn't a single number. It's the sum of three very different questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Business Value.&lt;/strong&gt; If we shipped this tomorrow, how much would users or the business care? Revenue, retention, a specific OKR. Concrete when you can, relative when you can't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time Criticality.&lt;/strong&gt; Does the value decay over time? A Black Friday feature shipped in December is worth approximately zero. A compliance deadline you miss is worth less than zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk Reduction / Opportunity Enablement.&lt;/strong&gt; Does this unlock something else, or take uncertainty off the table? Boring infrastructure work lives here and that's usually where it gets buried.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add those three together. That's Cost of Delay. Divide by Job Size. That's WSJF. The reason this works isn't because the numbers are accurate; it's because the &lt;em&gt;conversation&lt;/em&gt; is accurate. You can't pretend a risk-reduction spike is a revenue feature anymore. Every item has to justify itself on three axes before it gets a score.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why relative sizing beats hours every single time
&lt;/h2&gt;

&lt;p&gt;The other trap is how you size. People want to estimate in days. Don't. Human beings are terrible at estimating duration and we have decades of behavioral research showing it; &lt;a href="https://en.wikipedia.org/wiki/Parkinson%27s_law" rel="noopener noreferrer"&gt;Parkinson's law&lt;/a&gt; alone should be enough to scare you off. What humans are actually okay at is comparing two things and saying "that one's bigger."&lt;/p&gt;

&lt;p&gt;So score in &lt;a href="https://en.wikipedia.org/wiki/Fibonacci_number" rel="noopener noreferrer"&gt;Fibonacci&lt;/a&gt; (1, 2, 3, 5, 8, 13, 20) or T-shirt sizes (XS, S, M, L, XL, XXL). The gaps matter; a jump from 5 to 8 forces a conversation that "4 days vs 5 days" doesn't. Our tool supports both because teams argue about this, and the argument is not worth having. Pick one. Move on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rcy4qkdgqvapule0ymv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rcy4qkdgqvapule0ymv.webp" alt="WSJF prioritization results: ranked backlog with Business Value, Time Criticality, Risk Reduction, Job Size and WSJF score per item" width="800" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the tool actually does
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/agile-project-management/wsjf-calculator" rel="noopener noreferrer"&gt;WSJF Calculator&lt;/a&gt; runs in your browser. Nothing leaves your machine. I'm obsessive about this for product-management tools specifically; your roadmap is the kind of thing you really don't want sitting on someone else's server.&lt;/p&gt;

&lt;p&gt;Here's what we built into it after watching teams actually use it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Templates for common domains.&lt;/strong&gt; E-commerce, SaaS, internal platform, regulated industry. Start from something that already makes sense.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What-if analysis.&lt;/strong&gt; Inflate the top task's size by 25%. Does the ranking flip? If yes, your top priority is &lt;em&gt;fragile&lt;/em&gt;; re-estimate before you commit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robustness indicator.&lt;/strong&gt; If the top three WSJF scores are within 10% of each other, treat them as equal and let team capacity decide. The tool shows you this in real time so you stop pretending 4.20 is meaningfully bigger than 4.10.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share links.&lt;/strong&gt; Copy a URL, paste it in PI planning notes, everyone loads the same backlog state. No Jira exports, no CSVs floating around Slack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSV + PDF export.&lt;/strong&gt; Because some stakeholders only trust a PDF.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When WSJF is the wrong answer
&lt;/h2&gt;

&lt;p&gt;I'll save you a mistake I've made. WSJF is not a universal prioritization framework. It's the right tool when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have 15 or more roughly comparable backlog items.&lt;/li&gt;
&lt;li&gt;Your team is doing continuous delivery with short cycles.&lt;/li&gt;
&lt;li&gt;Cost of delay is actually variable across items (some are time-sensitive, some aren't).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's the &lt;em&gt;wrong&lt;/em&gt; tool when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a single strategic bet and three support tickets. Just do the strategic bet.&lt;/li&gt;
&lt;li&gt;Everything is equally urgent. Then nothing is, and you have a management problem, not a prioritization problem.&lt;/li&gt;
&lt;li&gt;You're trying to decide between two products. That's a &lt;a href="https://kitmul.com/en/agile-project-management/kano-model" rel="noopener noreferrer"&gt;Kano&lt;/a&gt; or portfolio question.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For binary in/out decisions, reach for &lt;a href="https://kitmul.com/en/agile-project-management/moscow-prioritization" rel="noopener noreferrer"&gt;MoSCoW&lt;/a&gt; or the &lt;a href="https://en.wikipedia.org/wiki/Eisenhower_matrix" rel="noopener noreferrer"&gt;Eisenhower matrix&lt;/a&gt; instead. For consumer-product feature ranking where you want a simpler formula, &lt;a href="https://kitmul.com/en/agile-project-management/rice-scoring" rel="noopener noreferrer"&gt;RICE&lt;/a&gt; is friendlier. I built versions of all three; they each solve a slightly different shape of problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The meeting ritual that actually works
&lt;/h2&gt;

&lt;p&gt;WSJF breaks down when it becomes a ritual. The calculator does the math; the humans have to do the talking. Here's the loop I've seen work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Score Cost of Delay first, together.&lt;/strong&gt; Use &lt;a href="https://kitmul.com/en/agile-project-management/scrum-poker" rel="noopener noreferrer"&gt;planning poker&lt;/a&gt; to surface disagreement. If two people scored a 3 and a 13, that's interesting; dig in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score Job Size &lt;em&gt;last&lt;/em&gt;.&lt;/strong&gt; If you know the size first, it anchors the value estimate. Humans are lazy that way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the top three out loud.&lt;/strong&gt; If anyone flinches, re-score.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lock and ship.&lt;/strong&gt; Don't re-score mid-sprint. The whole point is that yesterday-you and today-you had different gut feelings but the math didn't move.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For longer-horizon commitments, pair WSJF with probabilistic forecasting. I wrote a whole piece on &lt;a href="https://kitmul.com/en/blog/monte-carlo-forecasting-agile-delivery" rel="noopener noreferrer"&gt;Monte Carlo delivery forecasting&lt;/a&gt; that pairs nicely with this; one tool tells you &lt;em&gt;what&lt;/em&gt; to do next, the other tells you &lt;em&gt;when&lt;/em&gt; you'll realistically be done.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that surprised me
&lt;/h2&gt;

&lt;p&gt;When I first shipped the calculator, I expected engineers to use it. It turned out product managers are the heaviest users, and the thing they love most isn't the score. It's the &lt;em&gt;audit trail&lt;/em&gt;. Every ranking has the three sub-scores visible; when a stakeholder asks "why isn't my feature at the top", the PM can point at a number and say "because your Time Criticality is S and your Job Size is XL." The conversation ends in a minute, not a week.&lt;/p&gt;

&lt;p&gt;That's the real point of any prioritization tool. Not to replace judgment. To make judgment &lt;em&gt;visible&lt;/em&gt; enough that the loudest person in the room can't overwrite everyone else.&lt;/p&gt;

&lt;p&gt;Try it here: &lt;a href="https://kitmul.com/en/agile-project-management/wsjf-calculator" rel="noopener noreferrer"&gt;kitmul.com/en/agile-project-management/wsjf-calculator&lt;/a&gt;. It's free, it's in your browser, and your backlog is still yours.&lt;/p&gt;

</description>
      <category>agile</category>
      <category>scrum</category>
      <category>leadership</category>
      <category>productivity</category>
    </item>
    <item>
      <title>AVIF in 2026: The Complete Guide to the Image Format That Beat JPEG, PNG, and WebP</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Tue, 14 Apr 2026 19:41:39 +0000</pubDate>
      <link>https://dev.to/aralroca/avif-in-2026-the-complete-guide-to-the-image-format-that-beat-jpeg-png-and-webp-34n2</link>
      <guid>https://dev.to/aralroca/avif-in-2026-the-complete-guide-to-the-image-format-that-beat-jpeg-png-and-webp-34n2</guid>
      <description>&lt;p&gt;AVIF landed quietly in 2019 and spent years as the format nobody used. Then Chrome shipped native support. Then Firefox. Then Safari 16. By 2024, &lt;a href="https://caniuse.com/avif" rel="noopener noreferrer"&gt;Can I Use reported 93% global browser coverage&lt;/a&gt;. And suddenly the question flipped from "can I use AVIF?" to "why aren't I using AVIF?"&lt;/p&gt;

&lt;p&gt;If you're still serving JPEG and PNG on the web in 2026, you're leaving performance on the table. Here's what you need to know.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AVIF actually is
&lt;/h2&gt;

&lt;p&gt;AVIF (AV1 Image File Format) is a still-image format derived from the &lt;a href="https://en.wikipedia.org/wiki/AV1" rel="noopener noreferrer"&gt;AV1 video codec&lt;/a&gt;, developed by the &lt;a href="https://aomedia.org/" rel="noopener noreferrer"&gt;Alliance for Open Media&lt;/a&gt;; a consortium that includes Google, Apple, Microsoft, Mozilla, Netflix, and Amazon. It's royalty-free, open-source, and designed to replace JPEG, PNG, and even WebP.&lt;/p&gt;

&lt;p&gt;The key technical facts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lossy and lossless&lt;/strong&gt; compression in a single format&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10-bit and 12-bit&lt;/strong&gt; color depth (vs JPEG's 8-bit)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HDR and wide color gamut&lt;/strong&gt; (BT.2020, PQ, HLG)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpha transparency&lt;/strong&gt; (like PNG, unlike JPEG)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Film grain synthesis&lt;/strong&gt; (stores grain parameters instead of actual noise)&lt;/li&gt;
&lt;li&gt;Based on the &lt;strong&gt;HEIF container&lt;/strong&gt; (ISO/IEC 23008-12)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The compression comes from AV1's intra-frame coding tools: directional prediction, recursive partitioning (up to 128x128 superblocks), and the CDEF (Constrained Directional Enhancement Filter). These tools were designed for video but work remarkably well for still images.&lt;/p&gt;

&lt;h2&gt;
  
  
  The compression numbers
&lt;/h2&gt;

&lt;p&gt;Let's be specific. In independent tests by &lt;a href="https://netflixtechblog.com/avif-for-next-generation-image-coding-b1d75675fe4" rel="noopener noreferrer"&gt;Netflix&lt;/a&gt;, &lt;a href="https://blog.cloudflare.com/generate-avif-images-with-image-resizing/" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt;, and &lt;a href="https://web.dev/articles/serve-images-avif" rel="noopener noreferrer"&gt;Google&lt;/a&gt;, AVIF consistently outperforms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Comparison&lt;/th&gt;
&lt;th&gt;File size reduction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AVIF vs JPEG&lt;/td&gt;
&lt;td&gt;30-50% smaller at same quality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVIF vs PNG&lt;/td&gt;
&lt;td&gt;50-70% smaller (lossy mode)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVIF vs WebP&lt;/td&gt;
&lt;td&gt;15-25% smaller at same quality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a concrete example: a 500KB JPEG photograph typically compresses to ~250KB as AVIF with no visible quality difference. A 2MB PNG screenshot drops to ~400KB. These are not edge cases; they're typical results across diverse image types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbx4tseivnd8696twy5j.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbx4tseivnd8696twy5j.webp" alt="Analytics dashboard showing web performance metrics, representing the impact of image optimization" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AVIF matters for web performance
&lt;/h2&gt;

&lt;p&gt;Images account for &lt;a href="https://httparchive.org/reports/page-weight" rel="noopener noreferrer"&gt;roughly 50% of the average web page's total weight&lt;/a&gt;, according to HTTP Archive data. Cutting that by 30-50% has real consequences:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Core Web Vitals&lt;/strong&gt;: Smaller images directly improve LCP (Largest Contentful Paint). Google has confirmed LCP is a &lt;a href="https://developers.google.com/search/docs/appearance/core-web-vitals" rel="noopener noreferrer"&gt;ranking signal&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bandwidth costs&lt;/strong&gt;: A site serving 1 million page views/month with 500KB of images per page transfers ~500GB. Switching to AVIF cuts that to ~300GB. At CDN rates, that's real money.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mobile experience&lt;/strong&gt;: On 3G connections (still common in emerging markets), a 500KB image takes ~4 seconds to load. A 250KB AVIF takes ~2 seconds. That's the difference between a bounce and a conversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Carbon footprint&lt;/strong&gt;: Less data transferred means less energy consumed. The &lt;a href="https://www.thegreenwebfoundation.org/" rel="noopener noreferrer"&gt;Green Web Foundation&lt;/a&gt; estimates that data transfer accounts for ~0.06g CO2 per MB.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  AVIF vs WebP vs JPEG vs PNG: when to use each
&lt;/h2&gt;

&lt;p&gt;The format landscape isn't "use AVIF for everything." Each format still has its place:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;th&gt;Best format&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Photographs for the web&lt;/td&gt;
&lt;td&gt;AVIF&lt;/td&gt;
&lt;td&gt;Best compression, no visible quality loss&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transparent graphics&lt;/td&gt;
&lt;td&gt;AVIF or WebP&lt;/td&gt;
&lt;td&gt;Both support alpha; AVIF is smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pixel-perfect screenshots&lt;/td&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;Lossless, universal compatibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email attachments&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;Universal; every client supports it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legacy system input&lt;/td&gt;
&lt;td&gt;BMP/JPEG&lt;/td&gt;
&lt;td&gt;Some systems can't decode modern formats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Favicons&lt;/td&gt;
&lt;td&gt;ICO&lt;/td&gt;
&lt;td&gt;Required by browsers for tab icons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalable logos&lt;/td&gt;
&lt;td&gt;SVG&lt;/td&gt;
&lt;td&gt;Vector; infinitely scalable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HDR photography&lt;/td&gt;
&lt;td&gt;AVIF&lt;/td&gt;
&lt;td&gt;Only modern format with full HDR support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The practical advice: serve AVIF as your primary web format with JPEG/PNG fallbacks using the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element or CDN-based content negotiation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to convert images to and from AVIF
&lt;/h2&gt;

&lt;p&gt;You don't need to install command-line tools or pay for cloud services. Kitmul provides free, browser-based AVIF converters that process everything locally; your images never leave your device.&lt;/p&gt;

&lt;h3&gt;
  
  
  Converting TO AVIF (reduce file sizes)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/jpeg-to-avif" rel="noopener noreferrer"&gt;JPEG to AVIF Converter&lt;/a&gt;&lt;/strong&gt;: The most common conversion. Shrink your photo library by 30-50%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/png-to-avif" rel="noopener noreferrer"&gt;PNG to AVIF Converter&lt;/a&gt;&lt;/strong&gt;: Perfect for screenshots and graphics with transparency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/webp-to-avif" rel="noopener noreferrer"&gt;WebP to AVIF Converter&lt;/a&gt;&lt;/strong&gt;: Upgrade from WebP to the next generation; another 20% savings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/svg-to-avif" rel="noopener noreferrer"&gt;SVG to AVIF Converter&lt;/a&gt;&lt;/strong&gt;: Rasterize vector graphics into compact AVIF files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/bmp-to-avif" rel="noopener noreferrer"&gt;BMP to AVIF Converter&lt;/a&gt;&lt;/strong&gt;: Compress raw bitmaps from legacy systems; 95%+ reduction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/pdf-to-avif" rel="noopener noreferrer"&gt;PDF to AVIF Converter&lt;/a&gt;&lt;/strong&gt;: Extract PDF pages as lightweight AVIF images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/ico-to-avif" rel="noopener noreferrer"&gt;ICO to AVIF Converter&lt;/a&gt;&lt;/strong&gt;: Convert icon files for web galleries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Converting FROM AVIF (for compatibility)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/avif-to-jpeg" rel="noopener noreferrer"&gt;AVIF to JPEG Converter&lt;/a&gt;&lt;/strong&gt;: When you need universal compatibility for email or print.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/avif-to-png" rel="noopener noreferrer"&gt;AVIF to PNG Converter&lt;/a&gt;&lt;/strong&gt;: Lossless output with transparency for editing workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/avif-to-webp" rel="noopener noreferrer"&gt;AVIF to WebP Converter&lt;/a&gt;&lt;/strong&gt;: WebP fallback for CDN pipelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/avif-to-pdf" rel="noopener noreferrer"&gt;AVIF to PDF Converter&lt;/a&gt;&lt;/strong&gt;: Embed images in professional documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/avif-to-gif" rel="noopener noreferrer"&gt;AVIF to GIF Converter&lt;/a&gt;&lt;/strong&gt;: For email signatures and legacy platforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/avif-to-bmp" rel="noopener noreferrer"&gt;AVIF to BMP Converter&lt;/a&gt;&lt;/strong&gt;: Raw pixel data for industrial systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kitmul.com/en/image-design/avif-to-ico" rel="noopener noreferrer"&gt;AVIF to ICO Converter&lt;/a&gt;&lt;/strong&gt;: Create favicons from AVIF source images.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo97ai3dxultdxe4ibksb.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo97ai3dxultdxe4ibksb.webp" alt="Kitmul's AVIF converter tool showing an AVIF to WebP conversion with the converted result" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element: serving AVIF with fallbacks
&lt;/h2&gt;

&lt;p&gt;The standard pattern for progressive format delivery on the web:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo.avif"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo.webp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Description"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser picks the first format it supports. AVIF-capable browsers (93%+) get the smallest file. WebP serves as a fallback for the remaining ~7%. JPEG is the universal safety net.&lt;/p&gt;

&lt;p&gt;For responsive images, combine with &lt;code&gt;srcset&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo-400.avif 400w, photo-800.avif 800w, photo-1200.avif 1200w"&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;
    &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 800px) 100vw, 800px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;
    &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 800px) 100vw, 800px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo-800.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Description"&lt;/span&gt;
    &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
    &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt;
    &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  CDN and build-tool support
&lt;/h2&gt;

&lt;p&gt;Most modern infrastructure handles AVIF natively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Image Resizing&lt;/strong&gt;: &lt;a href="https://developers.cloudflare.com/images/polish/" rel="noopener noreferrer"&gt;Auto-converts to AVIF&lt;/a&gt; via Polish or Image Resizing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel/Next.js&lt;/strong&gt;: &lt;code&gt;next/image&lt;/code&gt; supports AVIF via &lt;code&gt;formats: ['image/avif', 'image/webp']&lt;/code&gt; in &lt;code&gt;next.config.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Netlify&lt;/strong&gt;: Automatic AVIF via &lt;a href="https://docs.netlify.com/image-cdn/overview/" rel="noopener noreferrer"&gt;Image CDN&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sharp (Node.js)&lt;/strong&gt;: Full AVIF encode/decode since v0.29&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Squoosh&lt;/strong&gt;: Google's &lt;a href="https://squoosh.app/" rel="noopener noreferrer"&gt;browser-based encoder&lt;/a&gt; supports AVIF&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;libavif&lt;/strong&gt;: The &lt;a href="https://github.com/AOMediaCodec/libavif" rel="noopener noreferrer"&gt;reference implementation&lt;/a&gt; by the AOM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mbg1bygfr5pwki5tfh5.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mbg1bygfr5pwki5tfh5.webp" alt="Server racks in a data center with network cables, representing CDN infrastructure for image delivery" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Known limitations
&lt;/h2&gt;

&lt;p&gt;AVIF isn't perfect. Be aware of these trade-offs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encoding speed&lt;/strong&gt;: AVIF encodes 5-10x slower than JPEG. This matters for real-time processing but not for batch/build-time conversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maximum dimensions&lt;/strong&gt;: The AV1 spec limits individual tiles to 8192x4320 pixels. Larger images require tiling, which some tools don't support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Animation support&lt;/strong&gt;: AVIF supports animated sequences (AVIS), but tooling is immature compared to GIF/WebP animation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Older browsers&lt;/strong&gt;: IE11 and pre-2020 browsers don't support AVIF. Always include fallbacks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Email clients&lt;/strong&gt;: Most email clients don't render AVIF. Use &lt;a href="https://kitmul.com/en/image-design/avif-to-jpeg" rel="noopener noreferrer"&gt;AVIF to JPEG&lt;/a&gt; for email content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Print workflows&lt;/strong&gt;: Print shops typically expect TIFF, PDF, or high-quality JPEG. Convert with &lt;a href="https://kitmul.com/en/image-design/avif-to-pdf" rel="noopener noreferrer"&gt;AVIF to PDF&lt;/a&gt; before sending to print.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;AVIF is the best general-purpose image format available in 2026. It delivers smaller files than any alternative at equivalent quality, supports features no other format offers (HDR, wide gamut, film grain synthesis), and has near-universal browser support.&lt;/p&gt;

&lt;p&gt;The migration path is straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convert your existing images to AVIF (use our &lt;a href="https://kitmul.com/en/image-design" rel="noopener noreferrer"&gt;free converters&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Serve AVIF with &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; fallbacks&lt;/li&gt;
&lt;li&gt;Keep JPEG/PNG originals for compatibility workflows&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every kilobyte you save loads faster, ranks better, and costs less. The format war is over. AVIF won.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Your Last Coffee Isn’t the Problem; the First Three Are Still in Your System</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Mon, 13 Apr 2026 19:37:09 +0000</pubDate>
      <link>https://dev.to/aralroca/your-last-coffee-isnt-the-problem-the-first-three-are-still-in-your-system-4kil</link>
      <guid>https://dev.to/aralroca/your-last-coffee-isnt-the-problem-the-first-three-are-still-in-your-system-4kil</guid>
      <description>&lt;p&gt;A friend of mine was averaging 4 cups of coffee a day. Morning espresso at 7. Drip coffee at 10. Post-lunch lungo at 14:00. And an afternoon ristretto around 16:00 "just to push through." He wasn't sleeping well, but blamed stress, screens, the usual suspects.&lt;/p&gt;

&lt;p&gt;I told him to do the math.&lt;/p&gt;

&lt;h2&gt;
  
  
  The exponential decay you're ignoring
&lt;/h2&gt;

&lt;p&gt;Caffeine follows &lt;a href="https://en.wikipedia.org/wiki/Elimination_(pharmacology)#First-order_elimination" rel="noopener noreferrer"&gt;first-order elimination kinetics&lt;/a&gt; with a half-life of approximately 5 hours in healthy adults. The formula is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dose&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elapsed_hours&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single 95mg drip coffee at 10:00 AM leaves ~47mg by 3 PM and ~24mg by 8 PM. Sounds harmless. But most of us don't drink a single cup.&lt;/p&gt;

&lt;p&gt;When you stack multiple intakes, the decay curves overlap. That 63mg espresso at 7 AM is almost gone by evening, but the 80mg lungo at 2 PM still has 40mg in your system at 9 PM. Add the 40mg ristretto at 4 PM and you're sitting at &lt;strong&gt;64mg of caffeine at bedtime&lt;/strong&gt;; well above the &lt;a href="https://www.sleepfoundation.org/nutrition/caffeine-and-sleep" rel="noopener noreferrer"&gt;50mg sleep disruption threshold&lt;/a&gt; identified in clinical research.&lt;/p&gt;

&lt;p&gt;The problem isn't any single cup. It's the superposition of all of them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frok4cruufm9fbmfl8qoz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frok4cruufm9fbmfl8qoz.webp" alt="Different types of coffee beans and brewing methods, each with a different caffeine content" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built a multi-intake caffeine tracker
&lt;/h2&gt;

&lt;p&gt;Most caffeine calculators I found online only handle one beverage. You enter "95mg at 8 AM" and get a decay curve. Useless if you're a multi-cup person; which is most of us, according to the &lt;a href="https://www.fda.gov/consumers/consumer-updates/spilling-beans-how-much-caffeine-too-much" rel="noopener noreferrer"&gt;FDA's average of 3-4 cups per day&lt;/a&gt; in the U.S.&lt;/p&gt;

&lt;p&gt;So I built one that handles the actual workflow: add as many beverages as you want, each with its own type and time, and see the &lt;strong&gt;combined&lt;/strong&gt; decay curve.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/health/caffeine-half-life" rel="noopener noreferrer"&gt;Caffeine Half-Life Calculator&lt;/a&gt; supports 11 beverage presets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Beverage&lt;/th&gt;
&lt;th&gt;Caffeine (mg)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ristretto&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Espresso&lt;/td&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lungo&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Drip Coffee&lt;/td&gt;
&lt;td&gt;95&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold Brew&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Matcha&lt;/td&gt;
&lt;td&gt;70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Energy Drink&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Black Tea&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Green Tea&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cola&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decaf&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can also enter custom amounts. Everything runs client-side in the browser; no data leaves your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The math behind the combined curve
&lt;/h2&gt;

&lt;p&gt;For N intakes, the total caffeine at time T is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;total(T) = sum(dose_i * 0.5 ^ ((T - t_i) / 5)) for all i where T &amp;gt;= t_i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each intake only contributes to the total &lt;em&gt;after&lt;/em&gt; its consumption time. The resulting curve isn't a simple exponential; it's a sum of shifted exponentials, which can produce surprising plateaus when intakes are spaced closely.&lt;/p&gt;

&lt;p&gt;This is why eyeballing it doesn't work. A 3 PM coffee "doesn't seem like much," but combined with the residual caffeine from morning drinks, it can push your bedtime levels past the threshold.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5633u94mmpnn71eddu7t.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5633u94mmpnn71eddu7t.webp" alt="A bed with white sheets, the place where caffeine levels finally matter" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What we learned about his consumption
&lt;/h2&gt;

&lt;p&gt;After plugging in his actual daily routine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;7:00 AM Espresso (63mg)&lt;/strong&gt; ; mostly gone by evening; only 5mg left at 11 PM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10:00 AM Drip Coffee (95mg)&lt;/strong&gt; ; still 17mg at 11 PM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2:00 PM Lungo (80mg)&lt;/strong&gt; ; 28mg at 11 PM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4:00 PM Ristretto (40mg)&lt;/strong&gt; ; 18mg at 11 PM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total at 11 PM: &lt;strong&gt;68mg&lt;/strong&gt;. That's 36% above the sleep threshold.&lt;/p&gt;

&lt;p&gt;Dropping the 4 PM ristretto brought him to 50mg; right at the edge. Moving the lungo to 1 PM dropped it to 43mg. That single hour shift made the difference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiohwshd309i2p8bawhpn.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiohwshd309i2p8bawhpn.webp" alt="Developer workspace with a coffee cup next to a laptop" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The developer who also drinks cold brew
&lt;/h2&gt;

&lt;p&gt;If you're a developer reading this; and statistically you probably are, given where I'm posting this; cold brew is particularly dangerous. At 200mg per serving, a single cold brew at 2 PM leaves &lt;strong&gt;71mg&lt;/strong&gt; in your system at 11 PM. By itself.&lt;/p&gt;

&lt;p&gt;Add that to a morning coffee and you're looking at 80+ mg at bedtime. No wonder you're staring at the ceiling at 1 AM wondering if it's the code review or the caffeine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical details
&lt;/h2&gt;

&lt;p&gt;The tool is built with React, runs entirely in the browser (no backend), and uses URL state for shareability. The decay chart uses a simple bar visualization with color coding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amber/dark&lt;/strong&gt;: high caffeine (&amp;gt;50% of peak)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amber/light&lt;/strong&gt;: moderate (below 50% of peak, above sleep threshold)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Green&lt;/strong&gt;: safe for sleep (below 50mg)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The source is part of &lt;a href="https://kitmul.com" rel="noopener noreferrer"&gt;Kitmul&lt;/a&gt;, a collection of 300+ free browser-based tools. If you're into health tracking, you might also find the &lt;a href="https://kitmul.com/en/health/bmi-calculator" rel="noopener noreferrer"&gt;BMI Calculator&lt;/a&gt;, &lt;a href="https://kitmul.com/en/health/bmr-calculator" rel="noopener noreferrer"&gt;BMR Calculator&lt;/a&gt;, or &lt;a href="https://kitmul.com/en/health/water-intake-calculator" rel="noopener noreferrer"&gt;Water Intake Calculator&lt;/a&gt; useful; staying hydrated actually helps your body &lt;a href="https://www.sleepfoundation.org/nutrition/caffeine-and-sleep" rel="noopener noreferrer"&gt;process caffeine more efficiently&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Track all your intakes, not just the last one.&lt;/strong&gt; Cumulative caffeine is what matters for sleep.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cutoff time depends on how many cups you've already had.&lt;/strong&gt; A 2 PM coffee is fine after one morning cup, but not after three.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold brew is not just "strong coffee."&lt;/strong&gt; At 200mg it's in a different category entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ristretto &amp;lt; Espresso &amp;lt; Lungo.&lt;/strong&gt; Shorter extraction = less caffeine. If you want an afternoon coffee, go short.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 50mg threshold is a population average.&lt;/strong&gt; If you're a &lt;a href="https://en.wikipedia.org/wiki/CYP1A2" rel="noopener noreferrer"&gt;slow metabolizer&lt;/a&gt; (CYP1A2 gene variant), your half-life could be 7+ hours. Adjust accordingly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Try the &lt;a href="https://kitmul.com/en/health/caffeine-half-life" rel="noopener noreferrer"&gt;Caffeine Half-Life Calculator&lt;/a&gt; with your actual daily intake. You might be surprised how much caffeine is still in your system at bedtime.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;All calculations run locally in your browser. No data is sent anywhere. The tool is free, open, and has no accounts or limits.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>mentalhealth</category>
      <category>science</category>
    </item>
    <item>
      <title>6 Agile Tools I Built Because Jira Dashboards Aren't Enough</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Sun, 12 Apr 2026 19:01:19 +0000</pubDate>
      <link>https://dev.to/aralroca/6-agile-tools-i-built-because-jira-dashboards-arent-enough-1m3e</link>
      <guid>https://dev.to/aralroca/6-agile-tools-i-built-because-jira-dashboards-arent-enough-1m3e</guid>
      <description>&lt;p&gt;I've been doing agile coaching and engineering management for long enough to know that most teams measure the wrong things. Or, more commonly, they measure nothing at all and just vibes-check their way through sprint planning. "How's the sprint going?" "Fine." "Are we on track?" "I think so." Cool. That's not data. That's horoscopes.&lt;/p&gt;

&lt;p&gt;The tools I'm about to walk through exist because I kept building the same spreadsheets over and over for different teams. WIP aging charts in Google Sheets. Capability matrices in Notion that nobody updated. Capacity plans in Excel that broke every time someone went on vacation. At some point I snapped and just built them properly — browser-based, no accounts, no servers, data stays on your machine.&lt;/p&gt;

&lt;p&gt;Here are six agile tools I shipped this week, what problems they solve, and why I think you might actually use them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfqxxntmxm4o31vnklse.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfqxxntmxm4o31vnklse.webp" alt="Team planning session with sticky notes and whiteboards" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your WIP is lying to you
&lt;/h2&gt;

&lt;p&gt;Every kanban board shows you how many items are in progress. Three items in dev, two in review, one in testing. Great. But that number is almost useless by itself.&lt;/p&gt;

&lt;p&gt;What matters isn't how many items are in progress — it's how long they've been there. A column with three items where each one arrived yesterday is fine. A column with three items where one has been sitting there for 22 days is a disaster hiding in plain sight.&lt;/p&gt;

&lt;p&gt;This is the core insight behind WIP aging, and it comes directly from &lt;a href="https://en.wikipedia.org/wiki/Little%27s_law" rel="noopener noreferrer"&gt;Little's Law&lt;/a&gt;: average cycle time equals work in progress divided by throughput. If your WIP includes ancient items, your average cycle time is being dragged up and your flow metrics are lying to you. &lt;a href="https://actionableagile.com/" rel="noopener noreferrer"&gt;ActionableAgile&lt;/a&gt; made this concept popular in the kanban world, and it's genuinely one of the most underrated agile metrics out there.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/agile-project-management/wip-age-chart" rel="noopener noreferrer"&gt;WIP Age Chart&lt;/a&gt; I built lets you visualize this instantly. Drop in your items, their start dates, and their current column — you get a scatter plot showing age by stage with configurable thresholds. Items aging past your 85th percentile cycle time get flagged red. No more "oh I didn't realize that ticket had been in code review for three weeks."&lt;/p&gt;

&lt;h2&gt;
  
  
  Six dimensions, one radar
&lt;/h2&gt;

&lt;p&gt;Here's a question that should be easy but never is: "Is the team healthy?"&lt;/p&gt;

&lt;p&gt;Not "are they delivering stuff" — that's one dimension. I mean the full picture. Are they delivering the &lt;em&gt;right&lt;/em&gt; stuff? Is their flow smooth or choppy? Can they make commitments and keep them? Is quality holding up or are they shipping fast and breaking things?&lt;/p&gt;

&lt;p&gt;Inspired by &lt;a href="https://en.wikipedia.org/wiki/Kanban_(development)" rel="noopener noreferrer"&gt;Daniel Vacanti&lt;/a&gt;'s work on kanban flow metrics, I built a &lt;a href="https://kitmul.com/en/agile-project-management/six-dimensions-radar" rel="noopener noreferrer"&gt;Six Dimensions Radar&lt;/a&gt; that scores teams across six axes: Quality, Responsiveness, Predictability, Productivity, Flow, and Value. You input your metrics, it renders a radar chart, and suddenly you can see that your team is crushing it on productivity but their predictability is garbage. That's a conversation starter. That's the kind of team performance visibility that turns a retrospective from "what went well / what didn't" into something with actual teeth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bus factor spreadsheet nobody maintains
&lt;/h2&gt;

&lt;p&gt;Every engineering org I've worked with has had some version of a skills matrix. Usually it's a Google Sheet that someone created during an offsite, got populated once with enthusiasm, and has been slowly rotting ever since. Meanwhile, the actual bus factor keeps getting worse and nobody notices until Sarah goes on maternity leave and suddenly nobody knows how the payment gateway works.&lt;/p&gt;

&lt;p&gt;T-shaped skills sound great in theory. In practice, nobody tracks them. The &lt;a href="https://kitmul.com/en/agile-project-management/capability-gap-analyzer" rel="noopener noreferrer"&gt;Capability Gap Analyzer&lt;/a&gt; makes it trivially easy: list your team members, list your capabilities, rate proficiency on a simple scale, and it immediately shows you where the gaps are. Single points of failure light up. Skills that only one person has get flagged. You can export the whole thing as JSON and actually keep it updated because it takes thirty seconds instead of an afternoon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2ghwgv1y1nh4of316x7.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2ghwgv1y1nh4of316x7.webp" alt="Dashboard showing agile metrics and flow data" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop forming teams by accident
&lt;/h2&gt;

&lt;p&gt;Most teams aren't designed. They're accidents. Someone gets hired, they join whichever team has capacity, and three months later you have a team of four backend engineers and zero frontend people trying to deliver a user-facing feature. &lt;a href="https://en.wikipedia.org/wiki/Conway%27s_law" rel="noopener noreferrer"&gt;Conway's Law&lt;/a&gt; predicts exactly what happens next: the architecture mirrors the team structure, and you end up with a beautiful API that nobody can actually use because the UI is an afterthought.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://teamtopologies.com/" rel="noopener noreferrer"&gt;Team Topologies&lt;/a&gt; by Matthew Skelton and Manuel Pais made a compelling case that team design is system design. I agree completely. The &lt;a href="https://kitmul.com/en/agile-project-management/team-formation-optimizer" rel="noopener noreferrer"&gt;Team Formation Optimizer&lt;/a&gt; takes your people, their skills, and your constraints (who works well together, who needs mentoring, what capabilities each team needs) and helps you explore formations that actually make sense. It won't replace human judgment — nothing should — but it surfaces combinations you wouldn't have thought of and highlights obvious imbalances before they bite you.&lt;/p&gt;

&lt;h2&gt;
  
  
  "How much work is coming?" is a forecasting problem
&lt;/h2&gt;

&lt;p&gt;Sprint planning usually focuses on what's already in the backlog. But the backlog isn't static. New items arrive constantly — bugs, feature requests, tech debt, that thing the CEO saw at a conference and now considers urgent. If you don't model the arrival rate, your capacity planning is fiction.&lt;/p&gt;

&lt;p&gt;This is a classic time series decomposition problem. The &lt;a href="https://kitmul.com/en/agile-project-management/backlog-arrival-rate-forecaster" rel="noopener noreferrer"&gt;Backlog Arrival Rate Forecaster&lt;/a&gt; uses multiplicative seasonal decomposition to break your historical backlog arrivals into trend, seasonal, and residual components. Feed it six months of data and it'll tell you that yes, backlog arrivals spike 40% every January (post-holiday feature requests) and drop 25% in August (everyone's on vacation). The approach follows the same principles outlined in &lt;a href="https://otexts.com/fpp3/" rel="noopener noreferrer"&gt;Hyndman &amp;amp; Athanasopoulos&lt;/a&gt;'s forecasting textbook — not because I'm trying to be academic, but because the methods work and they're well-understood.&lt;/p&gt;

&lt;p&gt;Knowing your delivery forecasting numbers means nothing if you don't also know what's coming in. Inflow matters as much as throughput.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capacity planning that accounts for reality
&lt;/h2&gt;

&lt;p&gt;The most common capacity planning I see is: "We have 5 devs × 10 points each = 50 points per sprint." This is wrong in so many ways I don't even know where to start. People take vacation. People get sick. People get pulled into incidents. New hires ramp up slowly. Seasonal factors affect availability — good luck staffing a full team between Christmas and New Year's.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/agile-project-management/seasonal-capacity-planner" rel="noopener noreferrer"&gt;Seasonal Capacity Planner&lt;/a&gt; accounts for all of this. You input your team composition, planned absences, hiring timeline, and seasonal adjustment factors. It produces a realistic capacity forecast that doesn't pretend everyone is available 100% of the time. This is basically the &lt;a href="https://en.wikipedia.org/wiki/Theory_of_constraints" rel="noopener noreferrer"&gt;Theory of Constraints&lt;/a&gt; applied to team capacity — your actual throughput is determined by your bottleneck, not your theoretical maximum. Sprint planning with realistic capacity numbers is a different experience entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  All of this runs in your browser
&lt;/h2&gt;

&lt;p&gt;I'm going to keep hammering this point because it matters: none of these free agile tools send your data anywhere. No servers. No accounts. No analytics tracking your team's performance data. Everything runs client-side in JavaScript. Your data lives in localStorage. You can export and import JSON files to move data between machines or share configurations with teammates.&lt;/p&gt;

&lt;p&gt;Most of the tools also support URL state — meaning you can configure a view and share the URL directly. Someone clicks it and sees exactly what you see. No login required.&lt;/p&gt;

&lt;p&gt;These are browser-based tools built for people who want to understand their teams better without handing their data to yet another SaaS vendor. If you're doing kanban flow analysis or trying to improve your agile metrics visibility, I think they'll save you time.&lt;/p&gt;

&lt;p&gt;I ship tools weekly. If there's something missing or broken, &lt;a href="https://github.com/aralroca/awesome-kitmul/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; or just tell me on Twitter. I read everything.&lt;/p&gt;

</description>
      <category>agile</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Detect AI-Generated Content Using Perplexity and Burstiness</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Thu, 09 Apr 2026 13:24:42 +0000</pubDate>
      <link>https://dev.to/aralroca/how-to-detect-ai-generated-content-using-perplexity-and-burstiness-gio</link>
      <guid>https://dev.to/aralroca/how-to-detect-ai-generated-content-using-perplexity-and-burstiness-gio</guid>
      <description>&lt;p&gt;A friend of mine who runs a content agency told me over coffee last week: "we've tried every AI detector out there and they're all snake oil." I told him I thought I could build a better one. He laughed. Fair enough.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/ai/ai-content-detector" rel="noopener noreferrer"&gt;AI Content Detector&lt;/a&gt; I built runs entirely in the browser. No uploads, no subscriptions, no cloud API charging you per scan. It uses ten statistical metrics and eighteen sentence-level signals to figure out whether text was written by a human or generated by ChatGPT, Claude, Gemini, or whatever LLM people are using this week. I want to explain how it actually works, because most "AI detector" marketing pages are deliberately vague about their methodology.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbnx8sp1snqnpposhe1cq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbnx8sp1snqnpposhe1cq.webp" alt="AI Content Detector analyzing a webpage with ten metrics" width="800" height="909"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why perplexity and burstiness alone don't cut it
&lt;/h2&gt;

&lt;p&gt;Every blog post about AI detection mentions perplexity and burstiness. They're real metrics, they do measure something useful, but here's the uncomfortable truth I discovered after weeks of testing: modern AI models like GPT-4 and Claude produce text with high perplexity and high burstiness. They've been trained to sound human. Relying on these two metrics alone is like trying to catch a burglar by checking if they used the front door.&lt;/p&gt;

&lt;p&gt;Perplexity measures how predictable word sequences are (low = robotic, high = creative). Burstiness measures sentence length variation (low = uniform, high = varied). Old-school AI from 2022 failed both tests spectacularly. But 2025-2026 models? They pass with flying colors.&lt;/p&gt;

&lt;p&gt;So what actually works?&lt;/p&gt;

&lt;h2&gt;
  
  
  The ten metrics that matter
&lt;/h2&gt;

&lt;p&gt;After benchmarking against articles I knew were AI-generated and articles I knew were human (I used a set of ten real URLs ranging from MIT Technology Review to generic SEO coffee blogs), I found that these signals, combined, produce results that are actually useful:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zipf's Law conformity&lt;/strong&gt; turned out to be the single most reliable metric. Every natural language follows Zipf's law: the second most common word appears half as often as the first, the third appears a third as often, and so on. Human text deviates from this curve because we get fixated on certain words, go on tangents, make weird word choices. AI text follows Zipf's law almost perfectly because it's sampling from probability distributions that inherently produce Zipfian outputs. I compute R-squared of log-rank vs log-frequency and anything above 0.96 is suspicious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repeated sentence starters&lt;/strong&gt; is embarrassingly simple but catches a ton of AI. Count what percentage of sentences start with the same word. AI loves starting sentences with "The", "This", "It", "In". I've seen AI blog posts where 70%+ of sentences start with one of four words. Humans are messier about it without even trying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Punctuation entropy&lt;/strong&gt; measures the Shannon entropy of distances between punctuation marks. AI places commas and periods at remarkably regular intervals. Humans are chaotic; sometimes we write three short sentences in a row, then a long one with five commas, then a fragment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sentence length skewness&lt;/strong&gt; captures the shape of the sentence length distribution. AI produces near-symmetrical distributions (bell curve). Humans write with positive skew: many short sentences, some medium ones, and the occasional monster sentence that runs away from you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hapax legomena ratio&lt;/strong&gt; counts what percentage of words appear only once in the text. Human text has more one-time words because we use specific, contextual vocabulary. AI reuses words more evenly across the text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paragraph uniformity&lt;/strong&gt; is the coefficient of variation of paragraph lengths. AI produces remarkably uniform paragraphs. Humans write a two-sentence paragraph followed by a twelve-sentence one without thinking about it.&lt;/p&gt;

&lt;p&gt;The remaining four metrics (perplexity, burstiness, vocabulary richness, word length standard deviation) contribute smaller weights. They help break ties but they're not the heavy hitters anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real trick: multiplicative signal scoring
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. Individual signals overlap between AI and human text all the time. A human might use dashes (AI signal) or have uniform paragraphs (AI signal). But humans almost never have dashes AND uniform paragraphs AND transition words AND no contractions AND formulaic structure AND repeated starters all in the same sentence.&lt;/p&gt;

&lt;p&gt;AI text has clusters of co-occurring signals. When three or more AI signals appear in the same sentence, the score doesn't just add up; it multiplies. A sentence with two AI signals scores normally. Three signals? Score multiplied by 1.5x. Four or more? Multiplied by 2x. This multiplicative approach captures something that linear scoring misses: the difference between "occasionally looks AI-ish" and "this is obviously a pattern."&lt;/p&gt;

&lt;p&gt;The sentence-level classifier tracks eighteen separate signals per sentence: length uniformity, dash usage, transition words, filler phrases ("it is important to note", "plays a crucial role"), overused vocabulary ("leverage", "comprehensive", "facilitate"), bold-then-explain patterns, "Here's what/why/how" hooks, proper noun density, contractions, parenthetical asides, questions, informal language, passive voice, starter repetition, colon endings, semicolons, numbered lists, and conclusion patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  URL mode and content extraction
&lt;/h2&gt;

&lt;p&gt;You can paste text directly or enter a URL. In URL mode, the tool fetches the HTML, strips out navigation, sidebars, footers, images, scripts, and all non-text elements, then converts the remaining content to Markdown using Turndown. You can expand the extracted content below the results to verify what the tool actually analyzed. Some sites load content via JavaScript (client-side rendering), which the fetcher can't capture; for those, the text tab works better.&lt;/p&gt;

&lt;p&gt;The URL fetch tries your browser first (no server involved). If CORS blocks it, a lightweight Edge proxy kicks in with a rate limit of five requests per minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it falls short
&lt;/h2&gt;

&lt;p&gt;I'm not going to pretend this is perfect.&lt;/p&gt;

&lt;p&gt;The biggest weakness: well-written AI text that has been lightly edited by a human. If someone generates a draft with ChatGPT and then rewrites a third of the sentences, adds a personal anecdote, and removes the transition words, our detector (and every other detector) will struggle. That's a fundamental limitation of statistical approaches.&lt;/p&gt;

&lt;p&gt;The second weakness: some human writing is genuinely formulaic. Corporate press releases, legal documents, academic abstracts. These trigger AI signals because they lack the messiness that statistical detectors look for. This isn't a bug exactly, but it does produce false positives on a category of text that nobody would call creative writing.&lt;/p&gt;

&lt;p&gt;The third weakness: very short text. Below about 200 words, there isn't enough statistical signal for any of the metrics to be reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compared to GPTZero, Originality.ai, Copyleaks
&lt;/h2&gt;

&lt;p&gt;Those services use trained ML classifiers (neural networks trained on millions of labeled AI/human samples). In theory, they should be more accurate than statistical heuristics like mine. In practice, the gap is smaller than you'd think, especially on longer texts. Their models were trained on specific AI outputs and struggle when new models appear; statistical patterns are more model-agnostic.&lt;/p&gt;

&lt;p&gt;The real advantage of the browser-based approach: your text never leaves your device, it's free, and it's instant. If you're scanning a hundred blog posts for a content audit, that matters more than a few percentage points of accuracy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://kitmul.com/en/ai/ai-content-detector" rel="noopener noreferrer"&gt;AI Content Detector&lt;/a&gt; is on Kitmul. Free, no signup, runs in your browser. Test it on something you know is AI-generated, test it on something you wrote yourself, and see if the results match your intuition.&lt;/p&gt;

&lt;p&gt;Next up: a sitemap scanner that crawls every URL in your sitemap.xml and produces a report of which pages look AI-generated. That one should be fun.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Related tools: &lt;a href="https://kitmul.com/en/ai/text-readability-scorer" rel="noopener noreferrer"&gt;Text Readability Scorer&lt;/a&gt; · &lt;a href="https://kitmul.com/en/ai/sentiment-analyzer" rel="noopener noreferrer"&gt;Sentiment Analyzer&lt;/a&gt; · &lt;a href="https://kitmul.com/en/ai/keyword-extractor" rel="noopener noreferrer"&gt;Keyword Extractor&lt;/a&gt; · &lt;a href="https://kitmul.com/en/ai/text-tone-analyzer" rel="noopener noreferrer"&gt;Text Tone Analyzer&lt;/a&gt; · &lt;a href="https://kitmul.com/en/ai/syllable-counter" rel="noopener noreferrer"&gt;Syllable Counter&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Perplexity" rel="noopener noreferrer"&gt;Perplexity (information theory)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Burstiness" rel="noopener noreferrer"&gt;Burstiness&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Zipf%27s_law" rel="noopener noreferrer"&gt;Zipf's law&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2301.11305" rel="noopener noreferrer"&gt;DetectGPT: Zero-Shot Machine-Generated Text Detection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2304.04736" rel="noopener noreferrer"&gt;On the Possibilities of AI-Generated Text Detection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>writing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Resting heart rate 68 to 56: what changed in my dev work</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Sat, 04 Apr 2026 15:39:11 +0000</pubDate>
      <link>https://dev.to/aralroca/resting-heart-rate-68-to-56-what-changed-in-my-dev-work-i13</link>
      <guid>https://dev.to/aralroca/resting-heart-rate-68-to-56-what-changed-in-my-dev-work-i13</guid>
      <description>&lt;p&gt;I normally write about web frameworks, WebAssembly, and JavaScript internals. And I normally don't publish on a Saturday. But I've been wanting to write this for a while and today I woke up inspired, so here it is.&lt;/p&gt;

&lt;p&gt;This isn't a technical article. It's personal. But I genuinely believe it can help a lot of people, especially developers and founders who spend long hours in front of a screen and feel like their brain gives up before their schedule does.&lt;/p&gt;

&lt;p&gt;I want to talk about the things that changed my daily performance more than any tool, framework, or productivity app ever did. Not hypothetical stuff I read on a blog. Things I've been doing for months (some for years) that produced measurable, repeatable differences in how I work.&lt;/p&gt;

&lt;p&gt;Here are the numbers first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resting heart rate: 68 → 56 bpm&lt;/li&gt;
&lt;li&gt;Breathing rate: 14-16 → 8-10 breaths/min&lt;/li&gt;
&lt;li&gt;Deep work blocks: ~90 min max → 3-4 hours consistently&lt;/li&gt;
&lt;li&gt;Post-meeting recovery: 20-30 min → basically instant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this came from a supplement, an app, or a course. It came from applying things I learned through competitive athletics to how I work as a developer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some context about me&lt;/li&gt;
&lt;li&gt;The parkour connection&lt;/li&gt;
&lt;li&gt;
Hack #1: Intermittent hypoxia

&lt;ul&gt;
&lt;li&gt;What it actually is&lt;/li&gt;
&lt;li&gt;What changed for me&lt;/li&gt;
&lt;li&gt;The science (briefly)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Hack #2: The Pomodoro technique, done right

&lt;ul&gt;
&lt;li&gt;Why most people do it wrong&lt;/li&gt;
&lt;li&gt;The parkour parallel&lt;/li&gt;
&lt;li&gt;How I actually use it&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Hack #3: Walking meetings&lt;/li&gt;

&lt;li&gt;Hack #4: Strategic caffeine&lt;/li&gt;

&lt;li&gt;Hack #5: Cold exposure&lt;/li&gt;

&lt;li&gt;Hack #6: Power naps&lt;/li&gt;

&lt;li&gt;What didn't work&lt;/li&gt;

&lt;li&gt;The thing nobody talks about: Silicon Valley already does this&lt;/li&gt;

&lt;li&gt;The physiological argument for founders&lt;/li&gt;

&lt;li&gt;How to start&lt;/li&gt;

&lt;li&gt;References&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Some context about me
&lt;/h2&gt;

&lt;p&gt;I've been in software development for over ten years. Most of that time I've been deep in open source. I created &lt;a href="https://github.com/aralroca/next-translate" rel="noopener noreferrer"&gt;NextTranslate&lt;/a&gt;, &lt;a href="https://github.com/teafuljs/teaful" rel="noopener noreferrer"&gt;Teaful&lt;/a&gt;, and more recently &lt;a href="https://brisa.build" rel="noopener noreferrer"&gt;Brisa&lt;/a&gt;, a web framework built on web components. I also recently built &lt;a href="https://kitmul.com/en" rel="noopener noreferrer"&gt;Kitmul&lt;/a&gt;, which went from a testing ground for my libraries to 300+ browser-based tools in three weeks (I wrote about that &lt;a href="https://aralroca.com/blog/ai-agents-should-be-the-app" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That's the professional side. But there's another side that's been part of my life for just as long: parkour.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parkour connection
&lt;/h2&gt;

&lt;p&gt;I started doing parkour in the mid-2000s. By 2011 I was competing in Red Bull events. Not casually. This was serious training, serious risk, serious discipline. I trained alongside people who are now elite athletes preparing for the Olympics. Parkour will officially be part of the Games, and some of the people I used to train with are on that path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-aral-redbull.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-aral-redbull.webp" alt="Aral competing at a Red Bull parkour event in Santorini" width="640" height="640"&gt;&lt;/a&gt;&lt;br&gt;&lt;small&gt;Red Bull Art of Motion, Santorini&lt;/small&gt;
  &lt;/p&gt;

&lt;p&gt;In 2021 I had the worst accident of my life. I misjudged a jump from a rooftop to a fence, fell badly, and ended up in a coma for three days. When I woke up, my vestibular system was damaged. The apparatus that controls balance. For weeks I couldn't walk straight without the world spinning.&lt;/p&gt;

&lt;p&gt;Most people would have quit parkour after that. I did the opposite. I used parkour as rehabilitation. I went back to basics. Simple movements, low risk, building balance from scratch. The mindset was the same one I apply to debugging: the jump wasn't the problem. My execution was. I analyzed what I did wrong, and I trained specifically to fix it.&lt;/p&gt;

&lt;p&gt;It took years of patient work. But this year, I went back and completed that exact same jump. Rooftop to fence. Clean.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/cGpxGp7wHG8"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I'm telling this story because it's directly relevant to everything that follows. The accident taught me something I already knew intellectually but had never felt in my bones: your body is the foundation of everything you do. When it breaks, nothing else matters. Not your code, not your startup, not your deadlines. And when you rebuild it deliberately, with discipline, everything else gets better too.&lt;/p&gt;

&lt;p&gt;These days I do parkour as a hobby to stay in shape. But the years of competitive training, the accident, the recovery, gave me something that no programming book or productivity course ever could: an intuitive understanding of how the body and brain actually perform under pressure. And how fragile that performance is if you don't take care of the hardware.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-aral-climbing.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-aral-climbing.webp" alt="Aral climbing natural rock formations" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;&lt;small&gt;Training outdoors&lt;/small&gt;
  &lt;/p&gt;

&lt;p&gt;Athletes know things about performance that knowledge workers generally ignore. How rest periods affect output quality. How breathing patterns change your nervous system state. How adrenaline management is a trainable skill, not a personality trait. How the difference between a good day and a bad day often comes down to physiology, not motivation. And how you recover from failure matters more than the failure itself.&lt;/p&gt;

&lt;p&gt;Once I started applying these principles to my work as a developer, everything changed.&lt;/p&gt;

&lt;p&gt;And exercise itself, just moving your body regularly, is the most underrated performance hack that exists. It increases BDNF (the protein that helps your brain form new connections), regulates cortisol, improves sleep, and directly enhances executive function. Everything else I'm about to describe works better on top of a foundation of consistent physical activity. Parkour is my thing, but any movement practice works.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Fz7hOUp0PXk"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Hack #1: Intermittent hypoxia
&lt;/h2&gt;

&lt;p&gt;This is the one that surprised me the most.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it actually is
&lt;/h3&gt;

&lt;p&gt;Intermittent hypoxia training (IHT) is simple: you alternate short periods of reduced oxygen breathing with normal recovery. It's the same principle behind altitude training, the thing that endurance athletes have been doing for decades to improve oxygen efficiency, except you can do it at sea level, sitting at your desk, in 15-30 minutes.&lt;/p&gt;

&lt;p&gt;The protocol: controlled breathing cycles that temporarily reduce your blood oxygen saturation, followed by recovery breathing. Repeat for several rounds. That's it.&lt;/p&gt;

&lt;p&gt;I started doing this to improve my breath-hold times and cardiovascular performance for parkour. The results in training were immediate. Longer runs, faster recovery between sequences, and much better composure during high-risk movements. When you're mid-air in a precision jump, the ability to manage your adrenaline response is not optional. IHT gave me noticeably more control over that.&lt;/p&gt;

&lt;h3&gt;
  
  
  What changed for me
&lt;/h3&gt;

&lt;p&gt;But the real surprise came outside of training sessions. And this is the part that I think matters for anyone who works with their brain.&lt;/p&gt;

&lt;p&gt;After about two weeks of consistent IHT practice, I noticed something: &lt;strong&gt;I was breathing more slowly throughout the entire day&lt;/strong&gt;. Not because I was trying to. My body had simply recalibrated. Where I used to take 14-16 breaths per minute sitting at my desk, I dropped to 8-10.&lt;/p&gt;

&lt;p&gt;This sounds minor. It's not.&lt;/p&gt;

&lt;p&gt;Patrick McKeown, author of &lt;em&gt;The Oxygen Advantage&lt;/em&gt;, has documented extensively how slower, lighter nasal breathing improves CO2 tolerance. Higher CO2 tolerance means better oxygen delivery to tissues, including your brain. It's counterintuitive (more CO2 = better oxygenation?), but the physiology is well-established: CO2 is what triggers hemoglobin to release oxygen to cells (the Bohr effect). If you breathe fast and shallow, you actually reduce oxygen delivery despite taking in more air.&lt;/p&gt;

&lt;p&gt;Here's what I noticed in my daily work after my breathing shifted:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sustained focus got dramatically easier.&lt;/strong&gt; I used to hit a wall at about 90 minutes of deep work. That wall moved to 3-4 hours. Not through willpower or discipline. I just didn't get tired as quickly. Better brain oxygenation, fewer stress hormones circulating, more stable energy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adrenaline management at work.&lt;/strong&gt; This was the one I didn't expect. Running a startup (or even just being a senior developer) means constant high-stakes moments. A production incident at 2am. A hard conversation with a coworker. An investor call where you have 20 minutes to make your case. Before IHT, these situations would leave me wired for hours afterward. Now the recovery is almost instant. The same nervous system control that helps me stay calm mid-air during parkour helps me stay clear-headed during a crisis at work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Faster cognitive recovery.&lt;/strong&gt; After an intense 3-hour coding session or a difficult meeting, I used to need a significant break before I could do anything useful again. Now I bounce back in minutes. It's like my brain's recovery time dropped from "restart the computer" to "close the tab and open a new one."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-meditation.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-meditation.webp" alt="Controlled breathing practice at sunrise" width="800" height="930"&gt;&lt;/a&gt;&lt;br&gt;&lt;small&gt;The simplest performance intervention: breathe less&lt;/small&gt;
  &lt;/p&gt;

&lt;h3&gt;
  
  
  The science (briefly)
&lt;/h3&gt;

&lt;p&gt;I'll keep this short because I'm a developer, not a scientist, but I did go down the rabbit hole on the research:&lt;/p&gt;

&lt;p&gt;A 2022 study in &lt;em&gt;Frontiers in Neuroscience&lt;/em&gt; found that IHT causes "proadaptive modifications" in the brain, stimulating BDNF (brain-derived neurotrophic factor) and increasing what they called "the adaptive potential, endurance, and working capacity of the brain" [1]. Another study showed significant gains in memory recall and attention in participants following IHT protocols [2].&lt;/p&gt;

&lt;p&gt;The mechanism is called &lt;strong&gt;hormesis&lt;/strong&gt;. Controlled, small doses of stress that make the body more resilient. Same principle as cold exposure, sauna, or fasting. The difference is that hypoxia specifically targets oxygen efficiency and neural adaptation.&lt;/p&gt;

&lt;p&gt;A study published in &lt;em&gt;Physiology&lt;/em&gt; documented that intermittent hypoxia upregulates three growth factors (EPO, BDNF, and VEGF) all directly linked to enhanced neural function and cellular resilience [10]. This isn't about feeling zen. It's about building a more capable brain at the physiological level.&lt;/p&gt;

&lt;p&gt;Andrew Huberman, a Stanford neuroscientist, has documented how breathing protocols shift autonomic nervous system state, reducing cortisol, increasing parasympathetic tone, and enhancing executive function [4]. IHT is essentially a more intense version of breathwork: it doesn't just teach you to breathe better in the moment. It permanently upgrades your baseline respiratory efficiency.&lt;/p&gt;

&lt;p&gt;My resting heart rate went from 68 to 56 bpm. That's not a small change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hack #2: The Pomodoro technique, done right
&lt;/h2&gt;

&lt;p&gt;I know, I know. Everyone's heard of Pomodoro. "25 minutes of work, 5 minutes of break, revolutionary." Most people try it for a week and drop it because it feels artificial.&lt;/p&gt;

&lt;p&gt;I did the same thing years ago. Then parkour taught me something that made me come back to it with a completely different understanding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why most people do it wrong
&lt;/h3&gt;

&lt;p&gt;The issue isn't the timer. It's what people do during the "break."&lt;/p&gt;

&lt;p&gt;Most developers hit the 5-minute break and immediately check Slack, scroll Twitter, read email, or look at their phone. That's not rest. That's a different kind of cognitive load. Your prefrontal cortex doesn't get to discharge. It just switches to a different task. When the timer starts again, you're not fresh. You're fragmented.&lt;/p&gt;

&lt;h3&gt;
  
  
  The parkour parallel
&lt;/h3&gt;

&lt;p&gt;Here's what parkour taught me about rest, and it took me years to really internalize this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You need rest to improve. The gains happen during recovery, not during effort.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a parkour training session, you give 100% on a sequence. A run, a series of jumps, a technical combination. Then you walk back. You breathe. You shake out your arms. You stand there for a minute doing literally nothing. And then you go again at 100%.&lt;/p&gt;

&lt;p&gt;If you skip that recovery and try to chain explosive movements back-to-back, two things happen: your performance degrades fast, and you get injured. Every serious practitioner learns this the hard way.&lt;/p&gt;

&lt;p&gt;Your brain works exactly the same.&lt;/p&gt;

&lt;p&gt;When you try to code for four straight hours without structured breaks, the last two hours are objectively worse. Your attention drifts. Your error rate climbs. You make architectural decisions you'll regret tomorrow. But you don't notice it in the moment because cognitive degradation is invisible from the inside.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I actually use it
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-focus.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-focus.webp" alt="Focused deep work session at a desk" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;&lt;small&gt;25 minutes of this, then 5 minutes of not-this&lt;/small&gt;
  &lt;/p&gt;

&lt;p&gt;Once I understood that the 5-minute break is not a concession to weakness but the actual mechanism that makes high performance sustainable, Pomodoro clicked for me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;25 minutes of full-intensity focus.&lt;/strong&gt; One task. No Slack. No email. No "quick check" on anything. If something pops into my head, I write it on a sticky note and go back to what I'm doing. The goal is to create a state of total immersion, the same mental state I'm in during a parkour sequence where I literally can't afford to think about anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5 minutes of real rest.&lt;/strong&gt; Stand up. Look out the window. Walk to the kitchen. Breathe. The key word is "real." Your eyes need to leave the screen. Your working memory needs to flush. If you don't do this, you're just doing 4 hours of gradually degrading work with arbitrary timer interruptions.&lt;/p&gt;

&lt;p&gt;The parallel to parkour is direct: train hard in bursts, rest completely between sets. The rest is what lets you sustain 100% intensity. Without it, by the third round you're operating at 60% and making mistakes. Except at your desk, the "injury" is a bug you'll spend two days debugging.&lt;/p&gt;

&lt;p&gt;Here's a trick I use that combines both hacks: &lt;strong&gt;during some Pomodoro breaks, I do a quick round of breath-hold exercises.&lt;/strong&gt; Five minutes of controlled breathing resets my autonomic nervous system and primes me for the next focus block. It's like a mini-reboot. When the timer starts again, I'm genuinely fresh, not just "took a break" fresh.&lt;/p&gt;

&lt;p&gt;After four Pomodoro cycles, I take a longer break of 15-20 minutes. Go outside if possible. Move. The compounding effect across a full day is dramatic. Hour six feels like hour one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hack #3: Walking meetings
&lt;/h2&gt;

&lt;p&gt;This one is simple but I almost never see people talk about it.&lt;/p&gt;

&lt;p&gt;Many meetings don't require you to be sitting at a desk staring at slides. Status updates, brainstorming sessions, 1-on-1s, planning discussions. For all of these, you can be walking.&lt;/p&gt;

&lt;p&gt;I use a walking treadmill at my desk during meetings. Slow pace, 3-4 km/h, just enough to keep blood flowing. The effects are immediate: better attention, less fidgeting, fewer distractions. There's something about low-intensity movement that keeps the brain engaged without consuming cognitive resources. Research backs this up: walking improves creative thinking and sustained attention.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-aral-treadmill.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-aral-treadmill.webp" alt="Aral walking on a treadmill desk while working" width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;&lt;small&gt;My walking treadmill setup. Most meetings don't require sitting.&lt;/small&gt;
  &lt;/p&gt;

&lt;p&gt;But here's the part nobody mentions: &lt;strong&gt;what happens after the meeting.&lt;/strong&gt; When you've been sitting for an hour-long call, you finish drained. You need a transition period before you can do real work again. When you've been walking during that same call, you finish energized. You sit down at your desk and you're immediately ready to work. The meeting didn't drain your battery. It charged it.&lt;/p&gt;

&lt;p&gt;This has been particularly useful for me during weeks with heavy meeting loads. The meetings themselves become light exercise, and the transitions between meetings and deep work become seamless.&lt;/p&gt;

&lt;p&gt;Obviously this doesn't work for every meeting. If you're pair programming, sharing your screen, or doing a code review where you need to type, sit down. But for the 60-70% of meetings that are primarily conversation, walking is strictly better than sitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hack #4: Strategic caffeine
&lt;/h2&gt;

&lt;p&gt;I've never been a big coffee drinker. But I noticed that the few times I did have coffee, the effect was massive. That got me thinking about why.&lt;/p&gt;

&lt;p&gt;The answer is simple: most people drink coffee every day, and daily caffeine consumption builds tolerance fast. After a couple of weeks, your morning coffee doesn't enhance your performance. It gets you back to your baseline. You're not getting a boost. You're paying a tax (dependency, sleep disruption, afternoon crashes) to feel normal. That's a bad trade.&lt;/p&gt;

&lt;p&gt;Because I don't have that daily habit, I can treat caffeine purely as a tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-coffee.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-coffee.webp" alt="Coffee cups" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;&lt;small&gt;What if the daily coffee ritual is actually costing you more than it gives?&lt;/small&gt;
  &lt;/p&gt;

&lt;p&gt;Most days I drink water. Just water. This means my caffeine tolerance stays low. Then, when I actually need it (I slept poorly and have a big day ahead, there's a product launch, I'm doing a full day of complex pair programming) a single coffee delivers a genuine cognitive boost. Alertness, processing speed, working memory, all measurably better because my body isn't habituated.&lt;/p&gt;

&lt;p&gt;Think of it like a power-up in a game. If you use it on every level, it stops being special. If you save it for the boss fight, it actually matters.&lt;/p&gt;

&lt;p&gt;The transition period when you stop daily coffee is about a week of mild headaches and low energy. After that, you reach a new normal where you feel fine without it, and caffeine becomes something you choose to deploy strategically rather than something you depend on to function.&lt;/p&gt;

&lt;p&gt;I know this one is controversial. Coffee culture is deeply embedded in developer identity. All I can say is: try it for two weeks and see what happens. The worst that can happen is you go back to your regular habit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hack #5: Cold exposure
&lt;/h2&gt;

&lt;p&gt;This is a quick one. A cold shower at the end of my normal shower, 60-90 seconds of cold water, produces a norepinephrine spike that improves alertness and mood for hours. This is well-documented by Huberman and others [4].&lt;/p&gt;

&lt;p&gt;I'm not doing ice baths or any extreme Wim Hof protocol. Just cold water at the end. The cost is minimal (it's uncomfortable for about 30 seconds, then you adapt). The effect on morning focus is noticeable and consistent.&lt;/p&gt;

&lt;p&gt;Wim Hof's method (breathing + cold + meditation) was actually validated in a Radboud University study that showed trained participants could voluntarily influence their sympathetic nervous system and innate immune response [8]. That's remarkable. But you don't need the full method to get the basic alertness benefit. Just turn the handle to cold for a minute at the end of your shower.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hack #6: Power naps
&lt;/h2&gt;

&lt;p&gt;When I hit a wall after lunch or after a heavy morning, a 20-30 minute nap resets me completely. Not a "nice to have." A genuine cognitive reboot.&lt;/p&gt;

&lt;p&gt;The key is keeping it under 30 minutes. Go longer and you enter deep sleep, which means you wake up groggy and worse than before. But a short nap, 20 minutes is the sweet spot, clears the mental fog and gives you what feels like a second morning. I've had some of my most productive afternoons right after a power nap.&lt;/p&gt;

&lt;p&gt;I don't schedule them. I just listen to my body. If I'm not tired, napping is pointless. But when the signal is there, fighting it with coffee or willpower is a losing strategy. The nap is faster, free, and has no side effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What didn't work
&lt;/h2&gt;

&lt;p&gt;I think it's important to mention what I tried that either didn't stick or didn't produce noticeable results. Not everything works for everyone, and I don't want to give the impression that I just tried five things and all five were magic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meditation apps.&lt;/strong&gt; I tried Headspace and Calm for a few months each. They're well-made products, but guided meditation didn't produce the same physiological changes as breathwork and IHT. My suspicion is that meditation works better as a long-term practice (years, not months) while breathing protocols produce measurable changes in weeks. Your mileage may vary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strict time-blocking the entire day.&lt;/strong&gt; I tried scheduling every 30-minute slot for a few weeks. It created more anxiety than productivity. Pomodoro works for me because it structures &lt;em&gt;intensity and rest&lt;/em&gt;, not &lt;em&gt;content&lt;/em&gt;. I decide what to work on, then I decide how intensely to focus on it. Scheduling every minute took away the flexibility that makes creative work possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing nobody talks about: Silicon Valley already does this
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-sv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Faralroca.com%2Fimages%2Fblog-images%2Fbiohack-sv.webp" alt="Modern tech office corridor" width="800" height="534"&gt;&lt;/a&gt;&lt;br&gt;&lt;small&gt;Behind the clean offices, a quiet obsession with physiological optimization&lt;/small&gt;
  &lt;/p&gt;

&lt;p&gt;Here's what I find interesting. These aren't fringe biohacking experiments. Breathwork and oxygen manipulation have been quietly adopted across the tech industry for years. Not as a trend, but as a serious performance tool.&lt;/p&gt;

&lt;p&gt;Bryan Johnson, the founder of Braintree (sold to PayPal for $800M), spends roughly $2M per year on biohacking protocols. The man literally moved his office into a hyperbaric chamber [5]. Now, $2M/year is absurd and not what I'm suggesting. But the underlying logic, that physiological optimization directly translates to cognitive performance, is sound.&lt;/p&gt;

&lt;p&gt;Jack Dorsey, co-founder of Twitter and Block, has practiced meditation and controlled breathing for over 20 years [6]. Tim Ferriss has dedicated entire podcast episodes to breathing protocols for performance, hosting James Nestor (author of the NYT bestseller &lt;em&gt;Breath: The New Science of a Lost Art&lt;/em&gt;) to discuss how subtle breathing adjustments transform cognitive output [7].&lt;/p&gt;

&lt;p&gt;Dave Asprey, founder of Bulletproof, has worked extensively with Wim Hof. Patrick McKeown's Oxygen Advantage method, which is essentially breath-hold training that simulates altitude, has been adopted by athletes, military operators, and increasingly, tech executives [3].&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Longevity Technology&lt;/em&gt; reported that biohacking has become "a major trend among Silicon Valley executives seeking to optimize health and performance," with breathwork, cryotherapy, and oxygen manipulation among the most commonly adopted protocols [9].&lt;/p&gt;

&lt;p&gt;What's telling is &lt;em&gt;why&lt;/em&gt; these people gravitate toward physiological hacks rather than (or in addition to) productivity software. When you're building something that demands 12-16 hours of sustained cognitive output per day, across months and years, the bottleneck is not your task manager. It's not your team structure. It's not your tech stack. &lt;strong&gt;The bottleneck is your brain's ability to maintain quality output under sustained pressure.&lt;/strong&gt; That's a physiology problem, not a tooling problem.&lt;/p&gt;

&lt;p&gt;And marginal gains in oxygen efficiency and stress resilience compound dramatically over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The physiological argument for founders
&lt;/h2&gt;

&lt;p&gt;The startup world glorifies hustle but ignores the hardware it runs on. You can optimize your deployment pipeline, your sprint process, your hiring funnel. But if your brain is running on shallow breathing and chronic cortisol, none of it matters. You're making your worst decisions at the end of the day, exactly when they matter most.&lt;/p&gt;

&lt;p&gt;Consider what changes when your baseline physiology is different:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your resting heart rate drops.&lt;/strong&gt; Mine went from 68 to 56 bpm. A lower resting heart rate correlates with better cardiovascular efficiency, better stress recovery, and better autonomic regulation. You're literally running calmer all day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your breathing rate drops.&lt;/strong&gt; 8 breaths per minute instead of 15. Fewer breaths means less sympathetic nervous system activation throughout the day. Less fight-or-flight. Less background anxiety. Less cortisol.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your work is structured around recovery.&lt;/strong&gt; Pomodoro ensures that hour six of your day is as sharp as hour one. You don't gradually degrade. You stay at peak performance in short bursts and actively recover between them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your oxygen utilization improves.&lt;/strong&gt; The same blood volume delivers more oxygen to your prefrontal cortex, the part of your brain that handles planning, decision-making, and impulse control. The exact functions you need most as a founder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your stress recovery accelerates.&lt;/strong&gt; The interval between "something went wrong" and "here's what we're going to do about it" shrinks from minutes to seconds. This is probably the most practically valuable change. In a startup, the speed at which you can move from panic to plan is everything.&lt;/p&gt;

&lt;p&gt;None of this is woo. James Nestor's research, documented across multiple peer-reviewed collaborations, shows that breathing efficiency is one of the single highest-leverage interventions for cognitive performance [7]. And a study published in &lt;em&gt;Physiology&lt;/em&gt; documented that intermittent hypoxia upregulates EPO, BDNF, and VEGF, three growth factors directly linked to neural function and cellular resilience [10].&lt;/p&gt;

&lt;h2&gt;
  
  
  How to start
&lt;/h2&gt;

&lt;p&gt;None of this requires expensive equipment or complicated protocols.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Intermittent hypoxia, the 5-minute version:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Breathe normally through your nose for 2 minutes. Just calm, quiet nasal breathing.&lt;/li&gt;
&lt;li&gt;Take a normal breath in, exhale gently, and hold your breath.&lt;/li&gt;
&lt;li&gt;Walk slowly while holding. When you feel a moderate urge to breathe, stop.&lt;/li&gt;
&lt;li&gt;Resume nasal breathing and recover for 1-2 minutes.&lt;/li&gt;
&lt;li&gt;Repeat for 6-8 rounds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a simplified version of Patrick McKeown's Oxygen Advantage method [3]. It works by increasing your CO2 tolerance and training your body to do more with less oxygen, exactly what altitude training does, but at sea level.&lt;/p&gt;

&lt;p&gt;For more structured sessions with timed rounds and progressive difficulty, I built an &lt;a href="https://kitmul.com/en/sport-performance/hypoxia-breathing-timer" rel="noopener noreferrer"&gt;intermittent hypoxia breathing timer&lt;/a&gt; as one of the tools on Kitmul.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pomodoro, the non-negotiable version:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pick one task. Not "a few things." One.&lt;/li&gt;
&lt;li&gt;Set a timer for 25 minutes.&lt;/li&gt;
&lt;li&gt;Work at full focus. No Slack, no email, no phone.&lt;/li&gt;
&lt;li&gt;When the timer rings, stop. Stand up. Walk away from your screen for 5 minutes.&lt;/li&gt;
&lt;li&gt;Repeat. After 4 cycles, take a 15-20 minute break.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The discipline is in the rest, not the work. Anyone can focus for 25 minutes. The hard part is actually stopping and actually resting. If you want a good timer, there's a &lt;a href="https://kitmul.com/en/agile-project-management/pomodoro-agile" rel="noopener noreferrer"&gt;Pomodoro timer on Kitmul&lt;/a&gt; too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caffeine reset:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stop drinking coffee for one week. Push through the headaches (they peak at day 2-3 and disappear by day 5). Then only use caffeine on days when you genuinely need a boost. You'll be amazed at how much more effective a single cup becomes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cold exposure:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the end of your normal shower, turn the water to cold for 60-90 seconds. That's it. The first week is uncomfortable. After that, it becomes almost pleasant, and the alertness benefit is consistent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Walking meetings:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Buy a cheap walking treadmill. Use it during any meeting where you don't need to type. You'll finish meetings energized instead of drained.&lt;/p&gt;




&lt;p&gt;I started all of this because of parkour. The breathing work, the structured rest, the body awareness. It all came from athletic training, not from reading productivity blogs. But the transfer to knowledge work was immediate and dramatic.&lt;/p&gt;

&lt;p&gt;The best productivity hack I've found in over ten years of professional software development isn't a tool, a framework, or an AI agent. It's optimizing the machine that runs all the other machines: your body.&lt;/p&gt;

&lt;p&gt;Oxygen and well-timed rest. That's it.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Rybnikova, E. &amp;amp; Nalivaeva, N. (2022). "Intermittent Hypoxic Training as an Effective Tool for Increasing the Adaptive Potential, Endurance and Working Capacity of the Brain." &lt;em&gt;Frontiers in Neuroscience&lt;/em&gt;. &lt;a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC9254677/" rel="noopener noreferrer"&gt;Read study&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Schega, L. et al. (2013). "Effects of Intermittent Hypoxia on Cognitive Performance and Quality of Life in Elderly Adults." &lt;em&gt;Gerontology&lt;/em&gt;. &lt;a href="https://pubmed.ncbi.nlm.nih.gov/23689305/" rel="noopener noreferrer"&gt;Read on PubMed&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;McKeown, P. &lt;em&gt;The Oxygen Advantage&lt;/em&gt;. Breath-hold exercises that simulate altitude training at sea level. &lt;a href="https://oxygenadvantage.com/pages/patrick-mckeown-m-a-tcd" rel="noopener noreferrer"&gt;Official site&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Huberman, A. "Breathwork Protocols for Health, Focus &amp;amp; Stress." &lt;em&gt;Huberman Lab&lt;/em&gt;. &lt;a href="https://www.hubermanlab.com/newsletter/breathwork-protocols-for-health-focus-stress" rel="noopener noreferrer"&gt;Read article&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Johnson, B. Braintree founder, $2M/year biohacking protocol including hyperbaric oxygen. &lt;a href="https://longevity.technology/news/silicon-valleys-biohacking-obsession-why-tech-executives-are-hooked/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dorsey, J. 20+ years of meditation and breathwork practice. &lt;a href="https://longevity.technology/news/silicon-valleys-biohacking-obsession-why-tech-executives-are-hooked/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nestor, J. &lt;em&gt;Breath: The New Science of a Lost Art&lt;/em&gt;. NYT bestseller on breathing science. &lt;a href="https://www.mrjamesnestor.com/" rel="noopener noreferrer"&gt;Official site&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wim Hof Method. Radboud University study on voluntary influence over sympathetic nervous system. &lt;a href="https://www.wimhofmethod.com/biohacking" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Silicon Valley's biohacking obsession: Why tech executives are hooked." &lt;em&gt;Longevity Technology&lt;/em&gt;. &lt;a href="https://longevity.technology/news/silicon-valleys-biohacking-obsession-why-tech-executives-are-hooked/" rel="noopener noreferrer"&gt;Read article&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dale, E. et al. (2014). "Unexpected Benefits of Intermittent Hypoxia: Enhanced Respiratory and Nonrespiratory Motor Function." &lt;em&gt;Physiology&lt;/em&gt;. &lt;a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC4073945/" rel="noopener noreferrer"&gt;Read study&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://kitmul.com/en/sport-performance/hypoxia-breathing-timer" rel="noopener noreferrer"&gt;Intermittent Hypoxia Breathing Timer&lt;/a&gt;. Free guided tool for structured IHT sessions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://kitmul.com/en/agile-project-management/pomodoro-agile" rel="noopener noreferrer"&gt;Pomodoro Timer&lt;/a&gt;. Free focus timer with structured work/rest cycles.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>mentalhealth</category>
      <category>beginners</category>
    </item>
    <item>
      <title>AI agents shouldn't control your apps; they should be the app</title>
      <dc:creator>Aral Roca</dc:creator>
      <pubDate>Tue, 31 Mar 2026 14:44:02 +0000</pubDate>
      <link>https://dev.to/aralroca/from-maintaining-open-source-libraries-to-building-an-ai-powered-tools-os-with-rust-and-webassembly-3eg4</link>
      <guid>https://dev.to/aralroca/from-maintaining-open-source-libraries-to-building-an-ai-powered-tools-os-with-rust-and-webassembly-3eg4</guid>
      <description>&lt;p&gt;&lt;a href="https://kitmul.com/en" rel="noopener noreferrer"&gt;Kitmul&lt;/a&gt; started as something far more modest than what it is today. I maintain two open source libraries: &lt;a href="https://github.com/aralroca/next-translate" rel="noopener noreferrer"&gt;NextTranslate&lt;/a&gt; and &lt;a href="https://github.com/teafuljs/teaful" rel="noopener noreferrer"&gt;Teaful&lt;/a&gt;. I needed a real Next.js project where I could iterate on them. Not artificial demos or example repositories; a live product where bugs surface naturally and limitations become obvious.&lt;/p&gt;

&lt;p&gt;That was the only goal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusnyhcygv1jtsoafzwlp.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusnyhcygv1jtsoafzwlp.webp" alt="Kitmul homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI multiplier effect
&lt;/h2&gt;

&lt;p&gt;To speed up development, I started using AI coding agents: Claude Code, Gemini, and Codex. Not just for productivity. I wanted to understand firsthand how these agents behave in a real development workflow. What they're good at, where they break, and how they change the way you think about building software.&lt;/p&gt;

&lt;p&gt;What I didn't expect was the effect on scope. When you can implement an idea in minutes instead of hours, you stop triaging ideas. You just build them. I went from "let me maintain these two libraries" to "let me build 300+ tools" in just 3 weeks.&lt;/p&gt;

&lt;p&gt;Currently I'm on Claude Code 20x. The combination of an agent that understands your codebase deeply and can execute multi-step tasks autonomously has been the biggest development velocity multiplier I've experienced.&lt;/p&gt;

&lt;h2&gt;
  
  
  From dev tools to tools for everyone
&lt;/h2&gt;

&lt;p&gt;As an open source developer, I've always built for other developers. Libraries, CLI tools, build utilities. Limited audience, limited impact.&lt;/p&gt;

&lt;p&gt;With Kitmul I flipped the question. Instead of "what tool does a dev need," I asked: "what tool do people search for on Google and end up on a website that charges them or uploads their files to a server."&lt;/p&gt;

&lt;p&gt;The answer: hundreds of tools. Remove image backgrounds, separate audio tracks, convert formats, compress PDFs, generate QR codes. Tools people use daily, and for which many sites charge €10-20/month.&lt;/p&gt;

&lt;p&gt;Today Kitmul has over 300. And they're not trivial wrappers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture: everything on the user's device
&lt;/h2&gt;

&lt;p&gt;Kitmul's fundamental technical decision is that everything runs on the client. No exceptions whenever possible.&lt;/p&gt;

&lt;p&gt;The stack is straightforward: if native JavaScript is enough, use JavaScript. If the operation is intensive (audio processing, heavy image manipulation, track separation) compile to WebAssembly. For performance-critical parts, Rust compiled to WASM.&lt;/p&gt;

&lt;p&gt;For example, here's how we merge PDFs entirely in the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PDFDocument&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pdf-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mergePDFs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;merged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;merged&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copyPages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPageIndices&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;merged&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;merged&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Returns Uint8Array, never leaves the browser&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero network calls. The file goes from &lt;code&gt;File API → pdf-lib → download&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Rust + WASM: the prime number checker
&lt;/h2&gt;

&lt;p&gt;For heavier computation, JavaScript hits a wall. A real example from Kitmul: our &lt;a href="https://kitmul.com/en/math/prime-number-checker" rel="noopener noreferrer"&gt;Prime Number Checker&lt;/a&gt;. JavaScript can check primality for small numbers, but try testing a number with more than 1,200 digits and the browser will choke. BigInt simply can't handle it.&lt;/p&gt;

&lt;p&gt;Here's the JavaScript approach, which works fine for numbers up to ~13 digits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isPrime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Works for small numbers, but for a 1200+ digit number?&lt;/span&gt;
&lt;span class="c1"&gt;// BigInt arithmetic becomes so slow the tab freezes.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The solution: we compiled a Rust crate that uses &lt;code&gt;num-bigint&lt;/code&gt; with a Miller-Rabin primality test to WASM. The Rust side receives the number as a string (because it can be thousands of digits long) and returns whether it's prime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;num_bigint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;num_traits&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;One&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Zero&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_number_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw_parts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;num_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;str&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_utf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num_str&lt;/span&gt;&lt;span class="py"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BigUint&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or_else&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;one&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;miller_rabin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then from JavaScript, we load the WASM module and pass the number as bytes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Load WASM and check a 1200+ digit number&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wasmBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;12345...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1200+ digit number&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numStr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wasm_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_number_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wasm_dealloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// result: 1 = prime, 0 = not prime&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript with BigInt can't handle numbers above ~1,200 digits. The Rust WASM module handles numbers of &lt;strong&gt;any size&lt;/strong&gt;; we've tested it with numbers over 3,000 digits. Same browser, same device, but Rust's &lt;code&gt;num-bigint&lt;/code&gt; crate uses optimized limb arithmetic that JavaScript simply can't match.&lt;/p&gt;

&lt;p&gt;The implications of this architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Near-zero infrastructure cost&lt;/strong&gt;: no servers processing files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real privacy, not promised&lt;/strong&gt;: data literally never leaves the device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability without provisioning&lt;/strong&gt;: each user brings their own compute.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The thesis: AI agents shouldn't control your apps. They should BE the app.
&lt;/h2&gt;

&lt;p&gt;This is where I think the current industry is getting it wrong.&lt;/p&gt;

&lt;p&gt;OpenAI with Operator, Anthropic with Computer Use, Google with Project Mariner: the big players are all building AI agents that &lt;strong&gt;control existing applications&lt;/strong&gt;. They take screenshots of your screen, move your mouse, click buttons, fill forms. Essentially they're building really sophisticated RPA bots.&lt;/p&gt;

&lt;p&gt;I think this approach is fundamentally flawed. Here's why:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. You're building on top of interfaces designed for humans, not machines.&lt;/strong&gt; When an AI agent navigates a website, it's fighting against dropdowns, modals, cookie banners, CAPTCHAs, and layout changes. Every website redesign can break the agent. This is fragile by design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. You still depend on third-party services.&lt;/strong&gt; The AI agent might be smart, but it's still uploading your PDF to iLovePDF, still sending your images to Canva's servers, still giving your data to someone else. The privacy problem doesn't go away just because a robot is clicking the buttons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. It's slow.&lt;/strong&gt; Screenshot → analyze → click → wait for page load → screenshot again. This loop takes seconds per action. Meanwhile, a direct function call takes milliseconds.&lt;/p&gt;

&lt;p&gt;The alternative: what I'm building with Kitmul is radically different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The AI agent doesn't control apps. The AI agent IS the app.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of navigating to SmallPDF to merge files, the agent calls &lt;code&gt;mergePDFs()&lt;/code&gt; directly. Instead of opening Canva to remove a background, it runs a WASM model in-browser. No screenshots, no mouse movements, no waiting for page loads. Direct function calls, direct results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The "screenshot and click" approach (Operator, Computer Use):&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Navigate to smallpdf.com          (~3s)&lt;/span&gt;
&lt;span class="c1"&gt;// 2. Find upload button                 (~1s)&lt;/span&gt;
&lt;span class="c1"&gt;// 3. Upload file                        (~5s)&lt;/span&gt;
&lt;span class="c1"&gt;// 4. Wait for processing                (~3s)&lt;/span&gt;
&lt;span class="c1"&gt;// 5. Click download                     (~2s)&lt;/span&gt;
&lt;span class="c1"&gt;// 6. Wait for download                  (~3s)&lt;/span&gt;
&lt;span class="c1"&gt;// Total: ~17 seconds + your files on someone else's server&lt;/span&gt;

&lt;span class="c1"&gt;// The Kitmul approach:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;merged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;mergePDFs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// ~300ms, never leaves your device&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a &lt;strong&gt;30-50x speed difference&lt;/strong&gt;, with the added benefit that your files never touch a remote server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Orchestration in practice
&lt;/h2&gt;

&lt;p&gt;Kitmul already has a built-in chat where the AI acts as an orchestrator. The user describes what they want in natural language. The AI selects tools from the catalog, executes them in sequence, and chains outputs.&lt;/p&gt;

&lt;p&gt;A concrete example: you upload an audio file. The AI separates it into tracks using a WASM source separation model. Then applies noise reduction to the vocal track. Converts the result to MP3. All chained, all in the browser, all without the file leaving your device.&lt;/p&gt;

&lt;p&gt;The orchestrator uses a tool registry that maps natural language intents to concrete functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified version of how the orchestrator works&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolRegistry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;merge_pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mergePDFs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file[]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;split_audio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;splitAudio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file[]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;compress_image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;compressImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ... 300+ more tools&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// The AI decides the execution plan, then runs it:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Split this song and remove noise from vocals&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → [{ tool: 'split_audio', input: userFile },&lt;/span&gt;
&lt;span class="c1"&gt;//    { tool: 'noise_reduction', input: '$prev.vocals' },&lt;/span&gt;
&lt;span class="c1"&gt;//    { tool: 'convert_to_mp3', input: '$prev' }]&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;toolRegistry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not a concept. It works today.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that gets really interesting: self-building tools
&lt;/h2&gt;

&lt;p&gt;Here's where Kitmul diverges from everything else.&lt;/p&gt;

&lt;p&gt;With 300+ tools, we cover a lot of use cases. But when a user asks for something we don't have, instead of saying "sorry, we can't do that," the system should be able to &lt;strong&gt;create the tool on the fly with AI&lt;/strong&gt;; and then, critically, have a &lt;strong&gt;human-in-the-loop&lt;/strong&gt; verify that the generated tool actually works correctly before it becomes part of the permanent catalog.&lt;/p&gt;

&lt;p&gt;Think about it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User asks: "I need a tool that converts MIDI files to sheet music."&lt;/li&gt;
&lt;li&gt;The AI generates the tool: a client-side implementation using WebAssembly.&lt;/li&gt;
&lt;li&gt;A human reviewer (me, or eventually a community of contributors) verifies the tool works, handles edge cases, and meets Kitmul's quality standards.&lt;/li&gt;
&lt;li&gt;Once approved, the tool is permanently added to the catalog.&lt;/li&gt;
&lt;li&gt;The next user who asks for the same thing gets the verified, production-quality tool instantly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The system literally builds itself based on what users need.&lt;/strong&gt; Every unanswered request becomes a signal. Every verified tool makes the platform more capable. It's a flywheel where AI generates, humans verify, and the catalog grows organically.&lt;/p&gt;

&lt;p&gt;This is fundamentally different from the "generate code at runtime" approach that some AI companies are pursuing. Generated code running without verification is a liability: it might have bugs, security holes, or simply not work for edge cases. The human-in-the-loop step is not a limitation; it's a &lt;strong&gt;feature&lt;/strong&gt;. It ensures every tool in the catalog is production-quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  See it in action
&lt;/h2&gt;

&lt;p&gt;Here's a quick demo of how Kitmul works:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/_CW7LiagTi8"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal: 4,000 tools in a year
&lt;/h2&gt;

&lt;p&gt;I have a backlog with over 4,000 tool ideas. It's not an arbitrary number: it's the actual size of the list after analyzing what people search for and what currently requires uploading files to a server or paying a subscription.&lt;/p&gt;

&lt;p&gt;With Claude Code 20x and the self-building approach, this is not a moonshot. Many tools are built in a single session. The more complex ones (those requiring custom WASM or signal processing) take longer, but they're still orders of magnitude faster than without AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The orchestration works for simple flows, but complex workflows with branching, conditionals, and feedback loops still need work. The self-building pipeline is being designed right now.&lt;/p&gt;

&lt;p&gt;The long-term vision: a system where any task you do today with fragmented software (uploading files here, paying a subscription there, installing an app for something else) can be resolved within a single interface, executed locally, orchestrated by AI, and constantly expanding based on what users actually need.&lt;/p&gt;

&lt;p&gt;The question I want to leave you with: &lt;strong&gt;Do we really need AI agents that puppet our existing apps? Or do we need to rethink what the app itself should be?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think the answer is the latter. And I think the browser is the right runtime to prove it.&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>ai</category>
      <category>rust</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
