<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Colas.Nahaboo.net - Blog</title>
    <subtitle>Colas Nahaboo personal site, with discussions about programming code, web and computing topics, surfing and SUPing, and various musings.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://colas.nahaboo.net/blog/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-08-31T00:00:00+00:00</updated>
    <id>https://colas.nahaboo.net/blog/atom.xml</id>
    <entry xml:lang="en">
        <title>Invent your own HTML tags!</title>
        <published>2026-08-31T00:00:00+00:00</published>
        <updated>2026-08-31T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/invent-your-own-html-tags/"/>
        <id>https://colas.nahaboo.net/blog/invent-your-own-html-tags/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/invent-your-own-html-tags/">&lt;p&gt;The HTML spec has had a proper way to invent your own tags since 2019. Most web developers seem to have missed it.&lt;/p&gt;
&lt;p&gt;Want a simple way to have a word in blue? just use &lt;code&gt;&amp;lt;ink-blue&amp;gt;word&amp;lt;/ink-blue&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;My &lt;a href=&quot;/blog/migration-of-this-site-to-the-new-zola-tera2&quot;&gt;migration of this site to Zola Tera 2&lt;/a&gt; forced me to rethink shortcodes and ad-hoc styling, which is what prompted me to dig into &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://html.spec.whatwg.org/multipage/custom-elements.html&quot;&gt;§4.13 of the HTML standard&lt;/a&gt; for the first time. I found three pieces, all now supported by every current engine.&lt;/p&gt;
&lt;h2 id=&quot;what&quot;&gt;What?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what&quot; aria-label=&quot;Anchor link for: what&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Custom elements are an old idea — Chrome shipped a v0 API in 2014, the cross-browser v1 standard followed a few years later. The pattern is straightforward: extend &lt;code&gt;HTMLElement&lt;/code&gt;, register the class via &lt;code&gt;customElements.define()&lt;/code&gt;. The simplest example, lifted from the spec, is a country-flag icon:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;font-style: italic;&quot;&gt; FlagIcon&lt;/span&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;font-style: italic;&quot;&gt; HTMLElement&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  constructor&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;    super&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_countryCode&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  static&lt;/span&gt;&lt;span&gt; observedAttributes&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;country&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;  attributeChangedCallback&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E64553;font-style: italic;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #E64553;font-style: italic;&quot;&gt; oldValue&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #E64553;font-style: italic;&quot;&gt; newValue&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_countryCode&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span&gt; newValue&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;_updateRendering&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;  connectedCallback&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;_updateRendering&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  get&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt; country&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;() {&lt;/span&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt; return&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_countryCode&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  set&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt; country&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E64553;font-style: italic;&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;) {&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;setAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;country&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span&gt; v)&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;customElements&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;define&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;flag-icon&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span&gt; FlagIcon)&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And use it as:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;flag-icon&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;&quot;&gt; country&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;nl&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;flag-icon&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;strong&gt;only&lt;/strong&gt; rule I had to learn the hard way: the name must contain a hyphen. &lt;code&gt;&amp;lt;flag-icon&amp;gt;&lt;/code&gt; works; &lt;code&gt;&amp;lt;flagicon&amp;gt;&lt;/code&gt; does not. The hyphen is the spec&#39;s way of ensuring your tag can never collide with a future native one.&lt;/p&gt;
&lt;p&gt;Three lifecycle hooks do most of the heavy lifting — &lt;code&gt;connectedCallback&lt;/code&gt;, &lt;code&gt;disconnectedCallback&lt;/code&gt;, &lt;code&gt;attributeChangedCallback&lt;/code&gt;. There is also &lt;code&gt;adoptedCallback&lt;/code&gt; (when your element moves documents) and the newer &lt;code&gt;connectedMoveCallback&lt;/code&gt; (added so the element keeps its state when moved inside the DOM without being disconnected). That is all there is to it.&lt;/p&gt;
&lt;h2 id=&quot;elementinternals&quot;&gt;ElementInternals&lt;a class=&quot;zola-anchor&quot; href=&quot;#elementinternals&quot; aria-label=&quot;Anchor link for: elementinternals&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is the piece that surprised me the most. Set one static field and call one method, and &lt;strong&gt;your custom element behaves like a real form control&lt;/strong&gt; — it appears in &lt;code&gt;form.elements&lt;/code&gt;, submits values, has &lt;code&gt;validity&lt;/code&gt;, &lt;code&gt;willValidate&lt;/code&gt;, and &lt;code&gt;labels&lt;/code&gt;. It also carries default accessibility semantics, so screen readers treat your tag like the proper role without you attaching ARIA manually:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;font-style: italic;&quot;&gt; MyCheckbox&lt;/span&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;font-style: italic;&quot;&gt; HTMLElement&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  static&lt;/span&gt;&lt;span&gt; formAssociated&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #FE640B;&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  static&lt;/span&gt;&lt;span&gt; observedAttributes&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;checked&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  constructor&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;    super&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_internals&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;attachInternals&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_internals&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;role&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;checkbox&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_internals&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;ariaChecked&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;addEventListener&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_onClick&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;bind&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;this&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;  attributeChangedCallback&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E64553;font-style: italic;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #E64553;font-style: italic;&quot;&gt; oldValue&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #E64553;font-style: italic;&quot;&gt; newValue&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_internals&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;setFormValue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;checked&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt; &amp;quot;on&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt; null&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;_internals&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;ariaChecked&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;checked&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  get&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt; checked&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;() {&lt;/span&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt; return&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;hasAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;checked&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;  set&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt; checked&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E64553;font-style: italic;&quot;&gt;flag&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;) {&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;toggleAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;checked&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt; Boolean&lt;/span&gt;&lt;span&gt;(flag))&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;  _onClick&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;() {&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;checked&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt; = !&lt;/span&gt;&lt;span style=&quot;color: #D20F39;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span&gt;checked&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;customElements&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;font-style: italic;&quot;&gt;define&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;my-checkbox&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;,&lt;/span&gt;&lt;span&gt; MyCheckbox)&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A nice extra: &lt;code&gt;this._internals.states.add(&quot;checked&quot;)&lt;/code&gt; plus the CSS &lt;code&gt;:state(checked)&lt;/code&gt; pseudo-class lets you flip states from JavaScript and style them with CSS, no attribute-flipping dance.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ElementInternals&lt;/code&gt; has been &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals&quot;&gt;Baseline widely available since March 2023&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;declarative-shadow-dom&quot;&gt;Declarative Shadow DOM&lt;a class=&quot;zola-anchor&quot; href=&quot;#declarative-shadow-dom&quot; aria-label=&quot;Anchor link for: declarative-shadow-dom&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The piece I missed most. &lt;code&gt;&amp;lt;template shadowrootmode=&quot;open&quot;&amp;gt;&lt;/code&gt; inside your custom element lets the shadow tree be &lt;strong&gt;rendered from pure HTML&lt;/strong&gt; — no JavaScript required for the initial render:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;my-component&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;&quot;&gt; shadowrootmode&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;open&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt; color&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;:&lt;/span&gt;&lt;span&gt; tomato&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt; }&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;Hello from a shadow root&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;my-component&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For static sites this is a game changer — Zola, Hugo, plain Markdown — your shadow tree ships as part of the HTML, the browser wires it up at parse time. No flash of unstyled component, no JS bundle needed.&lt;/p&gt;
&lt;p&gt;When upgrading from HTML that contains a declarative shadow root, check &lt;code&gt;ElementInternals.shadowRoot&lt;/code&gt; first — if it is already populated, your markup already shipped the tree and you should not call &lt;code&gt;attachShadow()&lt;/code&gt; again.&lt;/p&gt;
&lt;p&gt;Browser support landed between March 2023 and February 2024 — Chrome 111+, Safari 16.4+, Firefox 123+. There is also &lt;code&gt;shadowrootclonable&lt;/code&gt; and &lt;code&gt;shadowrootdelegatesfocus&lt;/code&gt; for cloning and focus delegation. See the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://web.dev/articles/declarative-shadow-dom&quot;&gt;Declarative Shadow DOM guide on web.dev&lt;/a&gt; for the details.&lt;/p&gt;
&lt;h2 id=&quot;closing&quot;&gt;Closing&lt;a class=&quot;zola-anchor&quot; href=&quot;#closing&quot; aria-label=&quot;Anchor link for: closing&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Three pieces, all in the HTML spec, all shipped in every current browser. The only thing missing was awareness. So, awareness raised — we no longer have any excuse to keep reinventing component frameworks. :-)&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>KXF: The Koala XML Form</title>
        <published>2026-08-30T00:00:00+00:00</published>
        <updated>2026-08-30T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/kxf-the-koala-xml-form/"/>
        <id>https://colas.nahaboo.net/blog/kxf-the-koala-xml-form/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/kxf-the-koala-xml-form/">&lt;div class=&quot;obsolete-overlay&quot;&gt;
    Legacy
&lt;/div&gt;
&lt;style&gt;
.obsolete-overlay {
    position: fixed;
    top: 40px;
    left: 60%;
    transform: translate(-50%, -50%) rotate(-5deg);
    font-size: 2vw;
    font-weight: 800;
    color: rgba(255, 0, 0, 0.4);
    background: rgba(255, 255, 0, 0.2);
    border: 15px solid rgba(255, 0, 0, 0.3);
    padding: 10px 20px;
    z-index: 9999;
    pointer-events: none;
    text-transform: uppercase;
    white-space: nowrap;
    user-select: none;
}
&lt;/style&gt;
&lt;p&gt;A blast from the past... In the last century, when we wrote XML by hand, I designed a format to get rid of one of XML multiple annoyances: as it used ordinary characters as deleimters, such as &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;amp;&lt;/code&gt;, it means often quoting hell.&lt;/p&gt;
&lt;p&gt;The idea: Use non-ascii-7bits characters as markup!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;«foo»&lt;/code&gt; to delimit tags, instead of &lt;code&gt;&amp;lt;foo&amp;gt;&amp;lt;/foo&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use these regular elements as escape sequences instead of entities. Escape &lt;code&gt;«&lt;/code&gt; by &lt;code&gt;«-»&lt;/code&gt;. Not really readable — but more than entities — but natural and consistent to parse.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wrote the KXF &amp;lt;-&amp;gt; XML converter in Klone, my lisp scripting language, that I definitely need to publish here as part of these legacy series.&lt;/p&gt;
&lt;p&gt;Here is the doc of the format:&lt;/p&gt;
&lt;div style=&quot;background-color: #eeffee;&quot;&gt;
&lt;h1&gt; KXF: The Koala XML Form&lt;/h1&gt;&lt;h2&gt;Purpose&lt;/h2&gt;
    The &lt;b&gt;Koala XML Form&lt;/b&gt; XML avatar has been defined with the following design 
    goals: 
    &lt;ul&gt;
      &lt;li&gt;Ease writing by hand&lt;/li&gt;
      &lt;li&gt;Ease human readability&lt;/li&gt;
      &lt;li&gt;Solve only syntaxic problems
	&lt;ul&gt;
          &lt;li&gt;no entities&lt;/li&gt;
          &lt;li&gt;no DTD&lt;/li&gt;
          &lt;li&gt;no CDATA&lt;/li&gt;
          &lt;li&gt;straightforward whitespace handling&lt;/li&gt;
          &lt;li&gt;get rid of most quoting hell: use less special chars, and use non ascii ones&lt;/li&gt;
        &lt;/ul&gt;&lt;/li&gt;
    &lt;/ul&gt;&lt;h2&gt;Design&lt;/h2&gt;&lt;p&gt;   Here are some examples:
    &lt;table&gt;
        &lt;tr&gt;
          &lt;th&gt;KXF&lt;/th&gt;
          &lt;th&gt;XML&lt;/th&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&amp;laquo;tag&amp;raquo;&lt;/td&gt;
          &lt;td&gt;&amp;lt;tag/&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&amp;laquo;tag foo &amp;lt;&gt; bar&amp;raquo;&lt;/td&gt;
          &lt;td&gt;&amp;lt;tag&gt;foo &amp;amp;lt; &amp;amp;gt; bar&amp;lt;/tag&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&amp;laquo;tag(x=y z=&quot;1 2&quot; t=&#39;gp&#39;) gee&amp;raquo;&lt;/td&gt;
          &lt;td&gt;&amp;lt;tag x=&#39;y&#39; y=&#39;1 2&#39; t=&#39;gp&#39;&gt;gee&amp;lt;/tag&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&amp;laquo;! comments&amp;raquo;&lt;/td&gt;
          &lt;td&gt;&amp;lt;!-- comments --&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&amp;laquo;? PIs&amp;raquo;&lt;/td&gt;
          &lt;td&gt;&amp;lt;?PIs?&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;&lt;p&gt;Quoting special chars:
	&lt;table&gt;
        &lt;tr&gt;
          &lt;th&gt;Char&lt;/th&gt;
          &lt;th&gt;Quoted form&lt;/th&gt;
          &lt;th&gt;Where&lt;/th&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&amp;laquo;&lt;/td&gt;
          &lt;td&gt;&amp;laquo;-&amp;raquo;&lt;/td&gt;
          &lt;td&gt;character data contents&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&amp;raquo;&lt;/td&gt;
          &lt;td&gt;&amp;laquo;+&amp;raquo;&lt;/td&gt;
          &lt;td&gt;character data contents&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&#39;&lt;/td&gt;
          &lt;td&gt;&amp;laquo;!&amp;raquo;&lt;/td&gt;
          &lt;td&gt;attribute values&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&#39;&lt;/td&gt;
          &lt;td&gt;&amp;laquo;/&amp;raquo;&lt;/td&gt;
          &lt;td&gt;attribute values&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&quot;&lt;/td&gt;
          &lt;td&gt;&amp;laquo;#&amp;raquo;&lt;/td&gt;
          &lt;td&gt;attribute values&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;&quot;&lt;/td&gt;
          &lt;td&gt;&amp;laquo;*&amp;raquo;&lt;/td&gt;
          &lt;td&gt;attribute values&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;&lt;ul&gt;
      &lt;li&gt;&amp;raquo;&amp;laquo;/tag&amp;raquo; optional ending forms can be used to check nesting as in
     &lt;br&gt;&lt;tt&gt;&amp;laquo;foo a very big contents... &amp;raquo;&amp;laquo;/foo&amp;raquo;&lt;/tt&gt;&lt;ul&gt;
          &lt;li&gt;ending contents is ignored and can be used for comments, as in:
    &lt;br&gt;&lt;tt&gt;&amp;laquo;foo a very big contents... &amp;raquo;&amp;laquo;/foo the main loop&amp;raquo;&lt;/tt&gt;&lt;/li&gt;
          &lt;li&gt;attributes if present must match the starting tag attributes:
    &lt;br&gt;
              &lt;tt&gt;&amp;laquo;foo(x=1) a very big contents... &amp;raquo;&amp;laquo;/foo(x=1)&amp;raquo;&lt;/tt&gt;
             matches, but
    &lt;br&gt;
              &lt;tt&gt;&amp;laquo;foo a very big contents... &amp;raquo;&amp;laquo;/foo(x=2)&amp;raquo;&lt;/tt&gt;
             raises an error
    &lt;/li&gt;
        &lt;/ul&gt;&lt;/li&gt;
      &lt;li&gt; Whitespace around sub-elements are discarded, but not around character data.
 &lt;br&gt;You can keep them 
 by postfixing element name with = (it sets the xml:space attribute to
 &quot;preserve&quot;), such as 
     &lt;br&gt;&lt;tt&gt;&amp;laquo;pre=(a=b) &amp;laquo;b x&amp;raquo; &amp;laquo;i y&amp;raquo;&amp;raquo;&lt;/tt&gt;
 or by enclosing them in the pseudo node &amp;laquo;= &amp;raquo;
&lt;br&gt;&lt;tt&gt;&amp;laquo;x &amp;laquo;=   &amp;raquo; &amp;laquo;y&amp;raquo; &amp;laquo;z&amp;raquo;&amp;raquo;&lt;/tt&gt;
 keeps space before y, but not between y and z
&lt;/li&gt;
      &lt;li&gt;For comfortable use, it is recommended to assign &amp;laquo;&amp;raquo; to 
shift-keypad-minus  and shift-keypad-plus respectively&lt;/li&gt;
      &lt;li&gt;Encodings are raw: either ISO-Latin-1, or UCS2, which can be autodetected 
 as fields must begin with &amp;laquo;&amp;lt;letter&gt; (ISO-Latin-1), \0&amp;laquo; (UCS2), &amp;laquo;\0 (MS UCS2)
&lt;/li&gt;
    &lt;/ul&gt;&lt;h2&gt;Benefits&lt;/h2&gt;&lt;ul&gt;
      &lt;li&gt;More readable&lt;/li&gt;
      &lt;li&gt;Most text editors know how to balance &amp;laquo; and &amp;raquo; better than 
    &amp;lt;foo&gt; and &amp;lt;/foo&gt;&lt;/li&gt;
      &lt;li&gt;It is self sufficient: whitespace handling is explicit&lt;/li&gt;
      &lt;li&gt;No need to quote the common chars &amp;lt;, &gt;, &amp;amp;&lt;/li&gt;
    &lt;/ul&gt;&lt;h2&gt;Drawbacks&lt;/h2&gt;&lt;ul&gt;
      &lt;li&gt;You cannot use XML Tools on this format. Not really a problem, as 
    you can convert to and from XML&lt;/li&gt;
    &lt;/ul&gt;&lt;h2&gt;Tools&lt;/h2&gt;
    For now, there exists only a parser/writer in 
    &lt;a href=&quot;ftp://koala.ilog.fr/klone&quot;&gt;Klone&lt;/a&gt; (&lt;tt&gt;xml-ksf.kl&lt;/tt&gt;, used to implement Klone
    scripts (&lt;tt&gt;xml2kxf&lt;/tt&gt;, &lt;tt&gt;kxf2xml&lt;/tt&gt;) that converts back and forth to XML.
&lt;p&gt;A java SAX parser is planned
&lt;h2&gt;Author&lt;/h2&gt;&lt;a href=&quot;http://colas,nahaboo.net&quot;&gt;Colas Nahaboo&lt;/a&gt;&lt;hr&gt;&lt;a href=&quot;index.html&quot;&gt;Back to XML Avatars&lt;/a&gt;
&lt;/div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Magnets, magnets everywhere</title>
        <published>2026-08-27T00:00:00+00:00</published>
        <updated>2026-08-27T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/magnets-magnets-everywhere/"/>
        <id>https://colas.nahaboo.net/blog/magnets-magnets-everywhere/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/magnets-magnets-everywhere/">&lt;p&gt;I have started putting magnets on small things around my desk. A cable that was wandering around now stays where I need it, and a USB hub now sits on the top of my PC case instead of taking space on the desk.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/magnets-magnets-everywhere/magnets-meme.jpg&quot; alt=&quot;Magnets, magnets everywhere&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;cables&quot;&gt;Cables&lt;a class=&quot;zola-anchor&quot; href=&quot;#cables&quot; aria-label=&quot;Anchor link for: cables&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For cables, I use round magnets with a hole in the middle. A small tie goes through the hole and loops over the cable. The cable rests on top of the magnet, and the magnet holds the whole thing to a magnetic surface.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/magnets-magnets-everywhere/3.jpg&quot; alt=&quot;A cable held by a ring magnet and a small tie&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I can move the cable, pull it away when I need it, and put it back without fighting a fixed clip. The magnet stays with the cable, so I do not have another small part to lose.&lt;/p&gt;
&lt;p&gt;The photo below also shows another version. I bolted a double-sided Velcro band through the central hole of a round magnet. It makes a reusable strap for a thicker cable or a small bundle.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/magnets-magnets-everywhere/4.jpg&quot; alt=&quot;Ring magnets with a cable tie and double-sided Velcro bands&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;usb-hubs&quot;&gt;USB hubs&lt;a class=&quot;zola-anchor&quot; href=&quot;#usb-hubs&quot; aria-label=&quot;Anchor link for: usb-hubs&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I glued square magnets (the leftlmost ones on the photo above)  made for cabinet doors to the sides of the USB hub. I used MS polymer glue and waited for it to cure. The magnets now attach the hub to the steel side of my PC case.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/magnets-magnets-everywhere/2.jpg&quot; alt=&quot;Square cabinet-door magnets glued to the sides of a USB hub&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The hub remains removable, but it stays put. The same trick should work with metallic desk legs, provided that the metal is magnetic.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/magnets-magnets-everywhere/1.jpg&quot; alt=&quot;USB hub attached to the side of a PC case&quot; /&gt;&lt;/p&gt;
&lt;p&gt;One small detail matters: a metal surface is not necessarily magnetic. I test it with one of the magnets first. I also let the glue cure fully before hanging the hub and keep strong magnets away from cards and magnetic storage.&lt;/p&gt;
&lt;p&gt;This is the kind of DIY I like: cheap parts, no drilling, and an arrangement I can change later.&lt;/p&gt;
&lt;p&gt;Buzz was right. Magnets, magnets everywhere. :-)&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>All my posts, on one page</title>
        <published>2026-08-26T00:00:00+00:00</published>
        <updated>2026-08-26T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/all-posts-page/"/>
        <id>https://colas.nahaboo.net/blog/all-posts-page/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/all-posts-page/">&lt;p&gt;At last, I added the page I was missing: &lt;a href=&quot;/about/posts/&quot;&gt;all my posts, ordered by date&lt;/a&gt;, in the same style as the &lt;a href=&quot;/blog/&quot;&gt;blog&lt;/a&gt;, &lt;a href=&quot;/code/&quot;&gt;code&lt;/a&gt; and &lt;a href=&quot;/surf/&quot;&gt;surf&lt;/a&gt; lists but for everything at once.&lt;/p&gt;
&lt;p&gt;Nothing fancy technically: the &lt;a href=&quot;/atom.xml&quot;&gt;RSS feed&lt;/a&gt; already did this for feed readers, so I just made a human-readable version of it. French twin posts are listed once, with their flags — newest first, from my &lt;a href=&quot;/code/first-ai-assisted-accepted-pr/&quot;&gt;first AI-assisted pull request&lt;/a&gt; down to my musings of 2007.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My Salli saddle chair</title>
        <published>2026-08-21T00:00:00+00:00</published>
        <updated>2026-08-21T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/salli-saddle-chair/"/>
        <id>https://colas.nahaboo.net/blog/salli-saddle-chair/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/salli-saddle-chair/">&lt;p&gt;I am an old programmer, and a game and surf addict. I have been spending hours and hours a day in a chair for decades: my work, then my evenings of computer games, are all done sitting. My sports — surfing, windsurfing, standup paddling — are wonderful for the body in the water, but alas, they do not fix the static hours spent at a desk. Over time, my hips started to stiffen, and I realized my sessions were not enough to compensate for all that sitting.&lt;/p&gt;
&lt;p&gt;So I decided to fix the problem where it happens: at the desk itself.&lt;/p&gt;
&lt;h2 id=&quot;why-a-saddle-chair&quot;&gt;Why a saddle chair?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-a-saddle-chair&quot; aria-label=&quot;Anchor link for: why-a-saddle-chair&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The idea of a saddle chair is to make you sit like you stand. On a normal chair your thighs are horizontal, at a 90° angle to your body, which presses your vertebrae and disks together at the front and strains the back muscles. A saddle chair opens the hip angle to about &lt;strong&gt;135°&lt;/strong&gt;, tilts your pelvis forward, and restores the natural S-curve of the spine instead of the slouched C of a regular seat. The weight goes on your sitting bones rather than your thighs, which is what your hips and knees like. It is a bit like sitting on a bicycle saddle, but on a proper chair.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/salli-saddle-chair/salli-posture.jpg&quot; alt=&quot;Salli posture&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sitting like standing: the pelvis forward, the spine in its natural S-curve.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-salli&quot;&gt;The Salli&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-salli&quot; aria-label=&quot;Anchor link for: the-salli&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I bought a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://salli.com/en/&quot;&gt;Salli&lt;/a&gt;, the Finnish pioneer of the saddle chair, with its patented two-part seat and an adjustable gap in the middle — which also keeps things dry and pressure-free down there, a nice bonus.&lt;/p&gt;
&lt;p&gt;The first days were promising for my hips. The main practical points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;You must raise your desk by 15 to 20 cm.&lt;/strong&gt; The saddle sits you higher than a normal chair. Conveniently, the tabletop height for saddle sitting works for standing too, so a standing desk handles both.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No backrest needed.&lt;/strong&gt; Once the pelvis is tilted forward, your back holds itself in its natural upright position and does not strain as it does slouched. I did not miss the backrest at all.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It is tiring at first.&lt;/strong&gt; The muscles that hold you upright are suddenly working, so I could only manage about an hour the first days. But you progress fast: after two weeks it was genuinely fine, and my hips clearly appreciated it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/salli-saddle-chair/colas-salli.jpg&quot; alt=&quot;My setup&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(my setup — a bit of a surprise to visitors, but worth it)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-note-for-the-desk-bound&quot;&gt;A note for the desk-bound&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-note-for-the-desk-bound&quot; aria-label=&quot;Anchor link for: a-note-for-the-desk-bound&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you work seated and have back or hip pain, it is worth knowing that in some places such a chair can be bought &lt;strong&gt;on a doctor&#39;s prescription&lt;/strong&gt;, like mine was — so check with your doctor or employer before paying full price yourself.&lt;/p&gt;
&lt;p&gt;Which prompted me, as usual, to think: if I am going to spend so many hours a day in a chair, the chair had better be a good one. My &lt;a href=&quot;/blog/why-a-walkpad-and-which-one&quot;&gt;walking pad&lt;/a&gt; fights the sitting, and now the Salli makes the sitting itself far less harmful. Two sides of the same problem.&lt;/p&gt;
&lt;p&gt;Long live not sitting like a lump!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why a walkpad, and which one</title>
        <published>2026-08-18T00:00:00+00:00</published>
        <updated>2026-08-18T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/why-a-walkpad-and-which-one/"/>
        <id>https://colas.nahaboo.net/blog/why-a-walkpad-and-which-one/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/why-a-walkpad-and-which-one/">&lt;p&gt;I never liked exercising. I love the physical effort required by surfing, windsurfing and standup paddling, but I was never able to run or swim as workouts because I get bored out of my mind so quickly.&lt;/p&gt;
&lt;p&gt;However, over 60, I do not have the motivation anymore to SUP or surf when the conditions are not fun (chop, onshore winds, rain, too big, rips...) so I cannot rely on my sessions to stay healthy. And sitting down all day to program or play games is literally lethal.&lt;/p&gt;
&lt;p&gt;The solution I decided on is a &lt;strong&gt;walking pad&lt;/strong&gt; — a bare, mini treadmill that you can slide under your couch when not in use and walk while working at a standing desk. I can thus watch YouTube videos on my PC screen right in front of me. I now look forward eagerly to my workouts (walkouts?) as I love watching science videos (Sabine Hossenfelder, PBS Space Time, Anton Petrov, or various geek, programming and AI topics). All this for less than 200€.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/why-a-walkpad-and-which-one/Fousae-ZX390.jpg&quot; alt=&quot;Fousae-ZX390&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(not me in the image, obviously :-) )&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The name of the game is to spend less time sitting. The studies agree: prolonged sitting is bad for the metabolism and the heart, and even light walking during desk work improves the numbers (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://pmc.ncbi.nlm.nih.gov/articles/PMC9883822&quot;&gt;Mayo Clinic NEAT study&lt;/a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://health.clevelandclinic.org/walking-pad-treadmill&quot;&gt;Cleveland Clinic&lt;/a&gt;). A walking pad is the lazy, home-friendly way to get some of that.&lt;/p&gt;
&lt;h2 id=&quot;why-a-walkpad-and-not-a-treadmill&quot;&gt;Why a walkpad, and not a treadmill?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-a-walkpad-and-not-a-treadmill&quot; aria-label=&quot;Anchor link for: why-a-walkpad-and-not-a-treadmill&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Because you do not run on a walking pad. You walk, at speeds up to jogging pace. And for walking, a full treadmill is overkill: it is bulky, heavy, very expensive, noisy, and its console full of buttons serves no purpose. A walking pad is cheaper, quieter, weighs 30-50 lbs, and fits under the couch. That is the whole point: it is there when you want it, out of sight when you do not.&lt;/p&gt;
&lt;p&gt;And why not just walk outside? Because outside I get bored instantly, and become a meal for tiger mosquitoes. My walking pad lets me combine a workout for both mind and body, independent of the weather.&lt;/p&gt;
&lt;p&gt;Also, the pad setting the pace for you is what makes it great compared to indoor bikes, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://repfitness.com/blogs/guides/what-is-a-manual-treadmill&quot;&gt;manual treadmills&lt;/a&gt;, rowing machines, etc. You do not have to think about your workout.&lt;/p&gt;
&lt;h2 id=&quot;which-one-to-buy&quot;&gt;Which one to buy?&lt;a class=&quot;zola-anchor&quot; href=&quot;#which-one-to-buy&quot; aria-label=&quot;Anchor link for: which-one-to-buy&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are many brands selling what are essentially the same machine (Urevo, Sperax, DeerRun, Costway, Kingsmith, GoPlus...), and the prices range from cheap to silly. A lot of advice exists, and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.reddit.com/r/treadmills/comments/v5l30p/walking_desks_how_bad_are_the_cheaps_vs_the/&quot;&gt;this reddit thread on cheap walking desks vs expensive ones&lt;/a&gt; gives a good feel of the issues — but read also the comments: they report feedback after months or years of use. There is also a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://ocdevel.com/walk&quot;&gt;handy summary of the offers&lt;/a&gt; made by a redditor.&lt;/p&gt;
&lt;p&gt;My own advice, after research and months of daily use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Brushless motor&lt;/strong&gt; for reliability and silence. This is the first thing to check.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standard Bluetooth FTMS protocol&lt;/strong&gt;, so that any app can drive it. This is crucial for geeks like me: I wrote my own app, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ColasNahaboo/walkpadspeed&quot;&gt;walkpadspeed&lt;/a&gt;, that drives my pad through my own routines. Without the standard protocol, you are locked into the vendor&#39;s app — often with subscriptions and bugs. With it, any good free app works.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High weight capacity&lt;/strong&gt; is an indication of sturdiness. Check the listed max weight.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incline matters&lt;/strong&gt;. Being able to incline the pad is great: you get the same workout at a lower speed, so less noise, less stress on the gear. &lt;strong&gt;Manual incline is OK&lt;/strong&gt; — automatic systems are heavier and bulkier to store, and not worth the tradeoff in my opinion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;6 support points beat 4&lt;/strong&gt; Having more support points brings greater reliability, as there is less flexing of the frame. Prioritize a solid, low-flex frame with firm rubber shock pads over a soft, springy walking surface for hardware longevity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Good shoes and a mat&lt;/strong&gt; give you a lot of shock absorption in any case, but is especially important with a low-flex frame. Slip-in shoes (e.g. Skechers) are especially nice if you have health issues.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;On cheap models, prefer many short sessions&lt;/strong&gt; instead of a long one, to avoid motor overheating.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A note about the &quot;slides under the couch&quot; selling point: sliding is actually a bit tricky, as you have to tilt most pads to use their wheels, and tilted, it does not fit under the couch. My solution was to create a sliding mat by gluing (with double-sided tape) a cheap &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=b_HQITSmBm0&quot;&gt;skating slideboard&lt;/a&gt; under a cardboard sheet, and now the pad slides effortlessly under the couch.&lt;br /&gt;
Some walkpads can fold in half and do not need to be tilted to use the rollers, so they can slide under a couch more easily, but some reviews say the folding can be felt underfoot while running, and is not pleasant.&lt;/p&gt;
&lt;h2 id=&quot;my-choice&quot;&gt;My choice&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-choice&quot; aria-label=&quot;Anchor link for: my-choice&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For what it is worth, I am quite satisfied with my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=PrnlVPZXXoY&quot;&gt;Fousae ZX-390&lt;/a&gt;, a simple entry-level pad. I bought it favoring mechanical qualities over sophisticated features, and it has everything I need: brushless motor, FTMS protocol, manual incline. Other brands sell similar pads.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Plus points:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it has 6 feet instead of 4, making it more durable — the deck does not flex — as the middle feet are positioned just where your feet land on the pad.&lt;/li&gt;
&lt;li&gt;it has a lubrication hole to pour the silicone oil into the belt, instead of having to deal with the messy operation of spreading it by hand.&lt;/li&gt;
&lt;li&gt;the motor housing at the front limits the length of your stride, compared to the rare models without it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Minus points:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;its belt is thinner than a high-end treadmill&#39;s, so walking barefoot will give you blisters fast&lt;/li&gt;
&lt;li&gt;no automatic incline: either 0% or 9%.&lt;/li&gt;
&lt;li&gt;its speed is limited to 6 km/h. To get to 12 km/h you have to raise the handlebar.&lt;/li&gt;
&lt;li&gt;to work at a desk, you cannot remove the handlebar; you have to fold it, and you can hit your heels on it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And of course, I wrote &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ColasNahaboo/walkpadspeed&quot;&gt;walkpadspeed&lt;/a&gt; to drive it, which I just released as v1 — see my &lt;a href=&quot;/code/walkpadspeed-v1&quot;&gt;announcement post&lt;/a&gt;. It loads routines from simple text files, and can even adjust the speed automatically to keep my heart rate in a chosen zone.&lt;/p&gt;
&lt;h2 id=&quot;my-advice&quot;&gt;My advice&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-advice&quot; aria-label=&quot;Anchor link for: my-advice&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You need to get used to it. Make short sessions at first, 0% incline, at very slow speeds, and raise the speed progressively each day, e.g. by 0.2 km/h.&lt;/li&gt;
&lt;li&gt;Once comfortable with it, you can set the incline to 9% and keep it there.&lt;/li&gt;
&lt;li&gt;Not all kinds of work are realistically doable on a walking pad. Avoid tasks that need precise mouse movements.&lt;/li&gt;
&lt;li&gt;Maintenance is essential. Oil it regularly and avoid dust and carpet lint.&lt;/li&gt;
&lt;li&gt;I use shoes, but walk barefoot once daily on one of my 15mn post-meal sessions. It keeps my feet in shape for surfing, where I walk a lot barefoot to get in and out of the water, but it is not enough to develop blisters or joint pains. However, you should not attempt to walk barefoot in your first month!&lt;/li&gt;
&lt;li&gt;I do not use socks for convenience (I only wear slaps at home), I just put my shoes on a gentle air blower I use to dry my wetsuit boots, to keep them sane.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;my-routines&quot;&gt;My routines&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-routines&quot; aria-label=&quot;Anchor link for: my-routines&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since the pad is always available, I built a small weekly program around it. Here are the routines I use the most:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Short Digestive&lt;/strong&gt;: a 15mn relaxed walk, done 15mn after each meal (thus 3 times a day), to lower the glycemic charge — the spike in sugar, and thus insulin, in the blood. It keeps the heart rate in &quot;Zone 0&quot;, because walking faster triggers the liver to release sugar in the blood, anticipating a need. It is also called a... &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Fart_walk&quot;&gt;Fart Walk&lt;/a&gt;! You can stop after just 5mn with most of the benefits, or lengthen it if you are watching a captivating video.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Z2 40mn&lt;/strong&gt;: the recommended brisk walk, the most efficient to burn fat. Must be done on an empty stomach. Staying in Zone 2 mobilizes fat burning without the stress of a faster walk or jog that triggers a cortisol spike and prevents fat burning. It &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.trainingpeaks.com/blog/zone-2-training-for-endurance-athletes/&quot;&gt;boosts endurance and metabolism&lt;/a&gt;. I do it 2 to 3 times a week.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Japan IWT 38mn&lt;/strong&gt;: the famous &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.theguardian.com/lifeandstyle/2025/aug/09/japanese-interval-walking-the-viral-exercise-trend-that-could-put-a-spring-in-your-step&quot;&gt;Japanese Interval Walking Training&lt;/a&gt; has proven extremely effective at enhancing cardio and fitness, and is a practical solution for walking pads, which are not designed to resist actual running. I do it once a week.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thus, my weekly schedule is 3 digestive walks after each meal, and per day of the week:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Japanese IWT&lt;/li&gt;
&lt;li&gt;Zone 2&lt;/li&gt;
&lt;li&gt;Resistance training&lt;/li&gt;
&lt;li&gt;Zone 2&lt;/li&gt;
&lt;li&gt;Resistance training&lt;/li&gt;
&lt;li&gt;Zone 2&lt;/li&gt;
&lt;li&gt;Rest, or resistance training if I feel like it&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Resistance training for me is short (20mn) but at the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=QxGQv7179OI&quot;&gt;highest intensity&lt;/a&gt;, as I am over 60.&lt;/p&gt;
&lt;p&gt;Two hours of episodes, one workout. I would not go back.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Cooking tip: weigh all your utensils</title>
        <published>2026-08-16T00:00:00+00:00</published>
        <updated>2026-08-16T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/cooking-tip-weigh-all-your-utensils/"/>
        <id>https://colas.nahaboo.net/blog/cooking-tip-weigh-all-your-utensils/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/cooking-tip-weigh-all-your-utensils/">&lt;p&gt;I have been cooking this way for years, and I am surprised it is not more common: I weigh all my pans, pots, bowls, colanders, plates, basically anything that can hold ingredients, and keep the list handy.&lt;/p&gt;
&lt;p&gt;You know the dance. The recipe says 300g of flour, so I put the bowl on the scale and tare. Then I want to add the sugar &lt;em&gt;in the same bowl&lt;/em&gt;, but the bowl is already on the scale with the flour in it — I do not know the tare anymore, so I do mental arithmetic, or I weigh each ingredient in its own bowl and wash more dishes than I cooked.&lt;/p&gt;
&lt;p&gt;With the weights written down, I never need to tare: pan on the scale, read the total, subtract its weight. A 1.2kg pan showing 1.8kg total — 0.6kg of food in it, exactly. It also gives me total transparency on portions: I can weigh the whole pot of pasta and divide by the number of plates without empty plates sitting around the kitchen.&lt;/p&gt;
&lt;p&gt;I keep the list on a post-it stuck on a shelf, but you can choose a note app (e.g. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://keep.google.com/&quot;&gt;Google Keep&lt;/a&gt;) — any paper sheet or note app works. Just keep it up to date.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bug reports: Favoring Prompt Requests over Pull Requests</title>
        <published>2026-08-15T00:00:00+00:00</published>
        <updated>2026-08-15T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/dont-do-pull-request-do-prompt-suggest/"/>
        <id>https://colas.nahaboo.net/blog/dont-do-pull-request-do-prompt-suggest/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/dont-do-pull-request-do-prompt-suggest/">&lt;p&gt;More and more often, I find a bug in some code that is not mine — often in a language or codebase I barely master. My reflex used to be to hack a fix anyway and send a pull request. But recently I spontaneously began to do the opposite: I let an AI agent fix the bug on a local copy, and instead of a pull request, I submitted the prompt I used — the one that seemed to fix the issue for me, passing the tests. An evolution of my &lt;a href=&quot;/blog/ai-without-ai&quot;&gt;AI without AI&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;I did this twice, recently: for the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/not-matthias/apollo/issues/183&quot;&gt;Apollo Zola theme&lt;/a&gt; and the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/co-l/openfox/issues/243&quot;&gt;Openfox AI harness&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Which prompted me to wonder whether this practice already had a name. I found the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.coderabbit.ai/blog/show-me-the-prompt-what-to-know-about-prompt-requests&quot;&gt;CodeRabbit post on prompt requests&lt;/a&gt;, which was right on the spot, but nothing else. Hence this post, to draw attention to the matter.&lt;/p&gt;
&lt;h2 id=&quot;what&quot;&gt;What?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what&quot; aria-label=&quot;Anchor link for: what&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The idea, in short: when you find a bug in a project, and you use an AI coding agent to fix it, &lt;strong&gt;do not submit the AI-generated pull request&lt;/strong&gt;. Submit the &lt;strong&gt;prompt&lt;/strong&gt; you used to fix the bug, with a comment that it seems to fix the bug on your setup, and passes the tests. Plus an overview of the useful info your AI investigation produced: the root cause analysis, the edge cases, the alternative paths tried.&lt;/p&gt;
&lt;p&gt;The maintainers can then run the prompt themselves, in the harness and the LLM they are comfortable with — not the one you happened to have at hand — refine it, grill the AI with a &lt;code&gt;grill-me&lt;/code&gt; style interrogation, and adjust it to their codebase. Instead of having the pain to review an unfamiliar PR.&lt;/p&gt;
&lt;p&gt;This is not my invention, the name already exists: &lt;strong&gt;prompt requests&lt;/strong&gt;. The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.coderabbit.ai/blog/show-me-the-prompt-what-to-know-about-prompt-requests&quot;&gt;CodeRabbit article&lt;/a&gt; traces the idea to a debate between &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://steipete.me/&quot;&gt;Peter Steinberger&lt;/a&gt;, creator of the self-hosted AI agent &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/clawdbot/clawdbot&quot;&gt;Clawdbot&lt;/a&gt;, and Gergely Orosz of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.pragmaticengineer.com/&quot;&gt;Pragmatic Engineer&lt;/a&gt;.
At first I was going to call it &quot;PS&quot; for &lt;strong&gt;Prompt Suggest&lt;/strong&gt;, but let&#39;s not reinvent the wheel.&lt;/p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why&quot; aria-label=&quot;Anchor link for: why&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Maintainers are drowning in &lt;strong&gt;PR slop&lt;/strong&gt;: AI-generated code that compiles, passes CI, and is utterly wrong for the codebase — style drift, redundant helpers, subtle architectural shortcuts. The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://asdlc.io/concepts/pr-slop/&quot;&gt;asymmetric velocity problem&lt;/a&gt;: an agent generates code in seconds that takes a human hours to review.&lt;/p&gt;
&lt;p&gt;The numbers are staggering: GitHub merged pull requests went from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.coderabbit.ai/blog/github-gives-maintainers-a-throttle-for-the-ai-pull-request&quot;&gt;25 million a month in January 2023 to 90 million a month in March 2026&lt;/a&gt;. A 3.6x increase, in an era where the number of human developers did not triple.&lt;/p&gt;
&lt;p&gt;The most spectacular example was the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.devclass.com/ai-ml/2025/11/27/ocaml-maintainers-reject-massive-ai-generated-pull-request/1728083&quot;&gt;13,000-line AI-generated pull request on the OCaml compiler&lt;/a&gt;, rejected by the maintainers, who cited the lack of review resources. The author, Joel Reymont, had &quot;carefully shepherded AI over the course of several days&quot;, and, asked why some files credited a maintainer as author, answered &quot;Beats me. AI decided to do so and I didn&#39;t question it.&quot;&lt;/p&gt;
&lt;p&gt;This is so bad that &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.blog/changelog/2026-02-13-new-repository-settings-for-configuring-pull-request-access&quot;&gt;GitHub now lets maintainers disable pull requests entirely&lt;/a&gt;, or restrict them to collaborators. Open source projects are starting to close their front door rather than drown.&lt;/p&gt;
&lt;p&gt;The root problem: &lt;strong&gt;code is now cheap&lt;/strong&gt;. As Jeremiah Lowin writes in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://jlowin.dev/blog/oss-maintainers-guide-to-saying-no&quot;&gt;An Open-Source Maintainer&#39;s Guide to Saying No&lt;/a&gt;: &quot;Historically, we could assume that since writing code is an expensive, high-effort activity, contributors would engage in discussion before doing the work. Today, LLMs have inverted this. Code is now cheap, and we see it offered in lieu of discourse.&quot;&lt;/p&gt;
&lt;p&gt;Which prompted me to think: if the code is the cheap part, then the value of my contribution is not the diff — it is the investigation. The bug I found, the root cause my AI uncovered, the proof that a fix exists and passes the tests. And the prompt, which is the recipe to reproduce the investigation.&lt;/p&gt;
&lt;h2 id=&quot;how&quot;&gt;How?&lt;a class=&quot;zola-anchor&quot; href=&quot;#how&quot; aria-label=&quot;Anchor link for: how&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So here is what I think I will put from now on in a bug report instead of a pull request:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color: #D20F39;font-weight: bold;&quot;&gt;Bug&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span&gt;: [short description, with a reproduction]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color: #D20F39;font-weight: bold;&quot;&gt;Prompt&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span&gt; (tested, fixes the bug on my setup, tests pass):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EA76CB;&quot;&gt;  &amp;gt; [the exact prompt(s) I gave to the agent]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color: #D20F39;font-weight: bold;&quot;&gt;Harness / model&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span&gt;: opencode / DeepSeek v4 flash (or Claude Code / ...)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color: #D20F39;font-weight: bold;&quot;&gt;Root cause&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span&gt;: [what the AI found]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color: #D20F39;font-weight: bold;&quot;&gt;Edge cases&lt;/span&gt;&lt;span style=&quot;color: #7C7F93;&quot;&gt;**&lt;/span&gt;&lt;span&gt;: [what the AI&amp;#39;s analysis surfaced]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The exact prompt is the key: like a minimal reproduction, it lets the maintainer run the fix in &lt;em&gt;his&lt;/em&gt; environment — the harness and model he trusts, in the context of his codebase. He can refine it, ask the AI questions, interrogate it about edge cases. I have a &lt;code&gt;grill-me&lt;/code&gt; skill in my own setup, I know it works :-)&lt;/p&gt;
&lt;h2 id=&quot;why-do-maintainers-should-like-it&quot;&gt;Why do maintainers should like it?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-do-maintainers-should-like-it&quot; aria-label=&quot;Anchor link for: why-do-maintainers-should-like-it&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No trust question&lt;/strong&gt;: the code is generated in the maintainer&#39;s own sandbox, by his own model, with his own system prompts. The question is no longer &quot;do I trust this stranger&#39;s code?&quot; but &quot;does my setup produce a good fix for this prompt?&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Architecture control&lt;/strong&gt;: the generated code follows the codebase conventions, because it is generated &lt;em&gt;in&lt;/em&gt; the codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The maintainer stays the author&lt;/strong&gt;: he is not inheriting 800 lines of alien code, he is applying an insight to his own project.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the contributor still gets the satisfaction of having found and fixed the bug — which is the valuable part anyway.&lt;/p&gt;
&lt;h2 id=&quot;am-i-reinventing-the-wheel&quot;&gt;Am I reinventing the wheel?&lt;a class=&quot;zola-anchor&quot; href=&quot;#am-i-reinventing-the-wheel&quot; aria-label=&quot;Anchor link for: am-i-reinventing-the-wheel&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Partly. The CodeRabbit article is more cautious than me: it argues prompt requests and pull requests are &lt;strong&gt;not in conflict&lt;/strong&gt;, and prompt requests work best &lt;em&gt;before&lt;/em&gt; pull requests — review the intent before generating, then still review the code that ships. That makes sense &lt;em&gt;within a team&lt;/em&gt;, where you will have to maintain the result, and where determinism, git blame and accountability matter.&lt;/p&gt;
&lt;p&gt;My point is narrower, and for a different case: the &lt;strong&gt;drive-by contribution&lt;/strong&gt;. When you fix a bug in a project that is not yours, and you have no intention to maintain the result — which is most bug reports — the prompt is a better unit of exchange than the diff. It is the &lt;a href=&quot;/blog/ai-without-ai&quot;&gt;AI without AI&lt;/a&gt; of bug fixing: I provide the prompt, you run it in your own wetware (or your own GPU).&lt;/p&gt;
&lt;p&gt;There are cases where a PR is still better: the trivial one-line fix, the case where you &lt;em&gt;will&lt;/em&gt; maintain the fix, or the project that explicitly asks for PRs. Use your judgment.&lt;/p&gt;
&lt;p&gt;So, next time your AI agent fixes a bug in somebody else&#39;s project: resist the urge to &lt;code&gt;git push&lt;/code&gt;. Open an issue, and give the maintainers the prompt. They will be grateful, and the code will be better for it.&lt;/p&gt;
&lt;p&gt;Maybe a  modern twist on the old saying &quot;dont give fishes, show how to fish&quot;.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Remediate subpixel color fringing on Linux</title>
        <published>2026-08-14T00:00:00+00:00</published>
        <updated>2026-08-14T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/remediate-subpixel-color-fringing-on-linux/"/>
        <id>https://colas.nahaboo.net/blog/remediate-subpixel-color-fringing-on-linux/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/remediate-subpixel-color-fringing-on-linux/">&lt;p&gt;I plugged in my new MSI 491CQPX, a QD-OLED ultrawide, and the first thing I noticed was that text looked dirty: every letter bordered by a red fringe on one side, a green one on the other. Not blurry, but colored — as if my glasses had chromatic aberration.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/remediate-subpixel-color-fringing-on-linux/fringing.jpeg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That is &lt;strong&gt;subpixel color fringing&lt;/strong&gt;. QD-OLED panels arrange their red, green, and blue subpixels in a triangle, while font rendering engines — ClearType, FreeType, all of them — assume the classic RGB stripes of LCD panels. Subpixel antialiasing is the culprit: it lights up individual subpixels to fake a higher resolution, and on a triangular layout the colors bleed sideways into a fringe.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://pcmonitors.info/articles/qd-oled-and-woled-fringing-issues/&quot;&gt;PC Monitors&lt;/a&gt; has the full story, with macro photos (QD-OLED and WOLED both suffer). &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://nuxx.net/blog/2026/01/09/oled-not-for-me/&quot;&gt;nuxx&lt;/a&gt; was so bothered that he returned his OLED — it made his eyes feel funny. I did not return mine: on Linux the fix is one setting.&lt;/p&gt;
&lt;h2 id=&quot;the-fix-grayscale-antialiasing&quot;&gt;The fix: grayscale antialiasing&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-fix-grayscale-antialiasing&quot; aria-label=&quot;Anchor link for: the-fix-grayscale-antialiasing&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Subpixel rendering is the problem, so I stopped using it. Set your fonts to plain grayscale antialiasing and the fringes disappear. On GNOME:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install GNOME Tweaks: &lt;code&gt;sudo apt install gnome-tweaks&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;Tweaks → Fonts&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Antialiasing&lt;/strong&gt; to &lt;strong&gt;Grayscale&lt;/strong&gt; — this is the whole fix&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The letters lose a bit of the LCD-crisp sharpness, but I had to look hard to tell the difference. Hinting is a matter of taste, not part of the fix: I left it alone.&lt;/p&gt;
&lt;h2 id=&quot;not-on-gnome&quot;&gt;Not on GNOME?&lt;a class=&quot;zola-anchor&quot; href=&quot;#not-on-gnome&quot; aria-label=&quot;Anchor link for: not-on-gnome&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Any desktop works — the switch is in fontconfig, the config file every Linux font stack reads. Create &lt;code&gt;~/.config/fontconfig/fonts.conf&lt;/code&gt; with this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;xml&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;&quot;&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;&amp;lt;!DOCTYPE&lt;/span&gt;&lt;span&gt; fontconfig SYSTEM &amp;quot;fonts.dtd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #8839EF;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;fontconfig&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;&quot;&gt; target&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;font&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;edit&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;&quot;&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;rgba&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #DF8E1D;&quot;&gt; mode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40A02B;&quot;&gt;&amp;quot;assign&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;none&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;edit&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #1E66F5;&quot;&gt;fontconfig&lt;/span&gt;&lt;span style=&quot;color: #179299;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;run &lt;code&gt;fc-cache -f&lt;/code&gt;, log out and back in. Setting &lt;code&gt;rgba&lt;/code&gt; to &lt;code&gt;none&lt;/code&gt; is precisely what turns subpixel rendering off.&lt;/p&gt;
&lt;h2 id=&quot;black-is-too-black&quot;&gt;Black is too black&lt;a class=&quot;zola-anchor&quot; href=&quot;#black-is-too-black&quot; aria-label=&quot;Anchor link for: black-is-too-black&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The fringes are most visible at maximum contrast — white text on pure black. I keep my editor and terminal backgrounds at a very dark gray (#121212) instead of #000000, which calms things down further and looks just as &quot;OLED&quot; to me.&lt;/p&gt;
&lt;h2 id=&quot;do-not-try-the-cleartype-tuner-under-wine&quot;&gt;Do not try the ClearType Tuner under Wine&lt;a class=&quot;zola-anchor&quot; href=&quot;#do-not-try-the-cleartype-tuner-under-wine&quot; aria-label=&quot;Anchor link for: do-not-try-the-cleartype-tuner-under-wine&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tempting, I know, but do not. The tuner writes Windows registry keys (&lt;code&gt;Software\Microsoft\Avalon.Graphics&lt;/code&gt;), which FreeType and Wayland never read — zero effect. And on Windows it would not help either: the tuner cannot adapt ClearType to a triangular layout, which is why there is a long-running &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/microsoft/PowerToys/issues/25595&quot;&gt;PowerToys issue&lt;/a&gt; begging Microsoft for OLED subpixel support.&lt;/p&gt;
&lt;p&gt;Alas, the Linux advantage here is real: Windows users are still waiting for Microsoft, while I fixed my monitor with one toggle. Done.&lt;/p&gt;
&lt;h2 id=&quot;but-still-annoyed-by-the-pixel-refresh&quot;&gt;... But still annoyed by the pixel refresh&lt;a class=&quot;zola-anchor&quot; href=&quot;#but-still-annoyed-by-the-pixel-refresh&quot; aria-label=&quot;Anchor link for: but-still-annoyed-by-the-pixel-refresh&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;However, I still have to cope with the other trouble with OLED monitors: They just stop working for 10 minutes at least once a day... at the most inconvenmient times: the dreaded &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://burnintest.org/blog/oled-pixel-refresh-explained/&quot;&gt;pixel refresh&lt;/a&gt;.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>WoWLAN: waking a suspended Linux host over wifi</title>
        <published>2026-08-11T00:00:00+00:00</published>
        <updated>2026-08-11T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/wowlan-wake-a-suspended-linux-host-over-wifi/"/>
        <id>https://colas.nahaboo.net/blog/wowlan-wake-a-suspended-linux-host-over-wifi/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/wowlan-wake-a-suspended-linux-host-over-wifi/">&lt;h2 id=&quot;what&quot;&gt;What?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what&quot; aria-label=&quot;Anchor link for: what&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I stumbled recently upon the fact that you can wake up a suspended Linux host over &lt;strong&gt;wifi&lt;/strong&gt;, not just Ethernet. The feature is called &lt;strong&gt;WoWLAN&lt;/strong&gt; — Wake on Wireless LAN — and, I must say, it took me by surprise.&lt;/p&gt;
&lt;p&gt;For me wifi always needs some complex dance to re-connect, and I could not imagine it could work. But with WoWLAN the card keeps running in a low-power listening mode, still associated to the access point, and it can wake the whole host when it sees the right packet. It is the wireless sibling of Wake-on-LAN, with one obvious advantage: no cable.&lt;/p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why&quot; aria-label=&quot;Anchor link for: why&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am setting up two cheap Linux &quot;AI servers&quot; at home:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a discounted &quot;Virtual Reality&quot; Zotac &quot;PC in a backpack&quot; with a GPU I have been using for two years now to transcribe confcalls with Whisper.&lt;/li&gt;
&lt;li&gt;a cheap PC with 3 GPUs of 12GB VRAM each made of spare parts and cheap second hand ones, to toy with the current ever-evolving crop of open source LLMs that are more powerful by the week.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wanted to suspend them when not actively running AI, but wake them transparently on demand. And with wifi, this meant I could move their noise and heat easily away from my &quot;work&quot; room.&lt;/p&gt;
&lt;h2 id=&quot;how&quot;&gt;How?&lt;a class=&quot;zola-anchor&quot; href=&quot;#how&quot; aria-label=&quot;Anchor link for: how&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Linux exposes it through the &lt;code&gt;iw&lt;/code&gt; tool, which is the least surprising part. Something like:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;iw phy0 wowlan show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sudo iw phy0 wowlan enable magic-packet disconnect&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can wake on a magic packet, on a disconnect, on any packet, or a combination. Then put the machine to sleep, fire a magic packet from your phone or another machine, and it comes back. A phone is the natural partner here — wake your laptop from the sofa before you even walk to it.&lt;/p&gt;
&lt;p&gt;Alas, it does not work everywhere. Not all wifi cards and drivers support it, so check the output of &lt;code&gt;iw list&lt;/code&gt; first. Intel cards are generally well served. The card also has to stay powered during suspend, so a machine that cuts wifi power entirely in suspend will not cooperate. And some distributions or NetworkManager versions may reset the setting at boot, so you may need to re-enable it — a systemd service fixes that.&lt;/p&gt;
&lt;p&gt;The tutorial I used, from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.cyberciti.biz/faq/configure-wireless-wake-on-lan-for-linux-wifi-wowlan-card/&quot;&gt;cyberciti.biz: how to configure wireless wake-on-lan for your Linux wifi card&lt;/a&gt;, walks through the whole thing: finding your phy, checking support, enabling WoWLAN, and testing it with &lt;code&gt;echo mem &amp;gt; /sys/power/state&lt;/code&gt;. For the low-level details, the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://wireless.docs.kernel.org/en/latest/en/users/documentation/wowlan.html&quot;&gt;official Linux wireless docs&lt;/a&gt; are the reference.&lt;/p&gt;
&lt;p&gt;The idea that a machine with a sleeping CPU is still listening for a whispered packet over the radio — and will wake up at a shout — amazes me more than it probably should :-)&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AI without AI</title>
        <published>2026-08-08T00:00:00+00:00</published>
        <updated>2026-08-08T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/ai-without-ai/"/>
        <id>https://colas.nahaboo.net/blog/ai-without-ai/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/ai-without-ai/">&lt;p&gt;Generative AI is currently morally bad, as most of it steals copyrighted works — but it would still be useful for people like me with no drawing skills. So I am increasingly using &lt;strong&gt;&quot;AI without AI&quot;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That is, I just post the prompt I would have used with a generative AI, and let the reader use his own wetware (aka &quot;Brain&quot;) — the &lt;strong&gt;NI&lt;/strong&gt; &lt;em&gt;(Natural Imagination)&lt;/em&gt; — to visualize the picture.&lt;/p&gt;
&lt;p&gt;As an example, in a reply to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/scalzi.com/post/3mruuefb7gs2a&quot;&gt;John Scalzi&#39;s post on Bluesky&lt;/a&gt; I described the book cover instead of generating it via AI:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;And for some AI-without-AI, here is the prompt to generate the cover in your own wetware (aka &quot;Brain&quot;):
&lt;em&gt;«A book cover for the next Sci-Fi humoristic novel of the fictional author John Barefoot titled &#39;The Brother Laser Printer Aficionados&#39;»&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The nice thing about running prompts on your wetware is that the model is local, free, and the output stays in your head. No credits, no seed, no style references, infinite resolution, perfect privacy. It renders instantly — the only downside being that nobody else gets to see the result.&lt;/p&gt;
&lt;p&gt;Also, it is something that has bothered me for a long time. As a boy, I was struck that during his famous 65-day survival drift across the Atlantic Ocean in 1952, narrated in his book &lt;em&gt;Naufragé Volontaire&lt;/em&gt;, French physician and adventurer Alain Bombard — aboard his boat &lt;em&gt;l&#39;Hérétique&lt;/em&gt; — took only a few personal items, including a pocket score of Beethoven&#39;s string quartets (specifically the 15th String Quartet in A minor, Op. 132) alongside Bach&#39;s Passions. He recounted that studying and mentally playing this complex music helped keep him sane and motivated during extreme isolation and hardship.&lt;/p&gt;
&lt;p&gt;I loved listening to Beethoven, but I could not fathom somebody actually &quot;listening&quot; by merely reading the score. It turns out he was doing AI-without-AI, ... decades before AI.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>And now... start posting!</title>
        <published>2026-08-07T00:00:00+00:00</published>
        <updated>2026-08-07T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/and-now-start-posting/"/>
        <id>https://colas.nahaboo.net/blog/and-now-start-posting/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/and-now-start-posting/">&lt;p&gt;I must say, I have been toying with the idea of posting more regularly here for a while. And now, at last, I decided myself to really start posting.&lt;/p&gt;
&lt;p&gt;Let me reassure you right away: &lt;strong&gt;this is not a social network.&lt;/strong&gt; I will not post reactions, reposts, or random thoughts the moment they cross my mind — no, I will not become yet another feed of instant takes. The last thing the world needs is &lt;em&gt;my&lt;/em&gt; version of the Bluesky noise. What I will post is things that pertain to my actual activities, not my mood.&lt;/p&gt;
&lt;p&gt;Which means: mostly &lt;strong&gt;&lt;a href=&quot;/code/&quot;&gt;coding&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href=&quot;/surf/&quot;&gt;surfing&lt;/a&gt;&lt;/strong&gt;, the two obsessions that occupy my days since I &lt;a href=&quot;/blog/retired-at-last&quot;&gt;retired&lt;/a&gt;, and everything that surrounds them. The occasional silly waste of a full weekend on an obscure terminal command that only I will ever use. The existential satisfaction of a clean configuration file. A tool I built and decided to share openly.&lt;/p&gt;
&lt;p&gt;Does this mean a post every single day? No. That would be a nice pledge, but I know myself too well to pretend I will hold that rhythm. I made that mistake once, &lt;a href=&quot;/blog/retired-at-last&quot;&gt;in 2021&lt;/a&gt;, and I was right to be skeptical of it. So: no strict schedule, no guilt, just a sincere intention to write more, and to write about things that matter to me.&lt;/p&gt;
&lt;p&gt;There is a quiet pleasure in it. Publishing on a corner you own, with zero algorithmic pressure and a total absence of pop-up newsletter modals, feels a bit vintage — like casting a message in a bottle into an ocean of infinite scroll. What changed is that now, this message may be found not by a human reader but an AI agent that will feed it to the giant automated ideas fisheries that has become Internet.&lt;/p&gt;
&lt;p&gt;So, here is the promise I make to you, dear biologic or electronic — or imaginary - reader: &lt;strong&gt;One post every single day&lt;/strong&gt;, until ... not.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Migration of this site to the new Zola Tera2</title>
        <published>2026-08-06T00:00:00+00:00</published>
        <updated>2026-08-06T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/migration-of-this-site-to-the-new-zola-tera2/"/>
        <id>https://colas.nahaboo.net/blog/migration-of-this-site-to-the-new-zola-tera2/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/migration-of-this-site-to-the-new-zola-tera2/">&lt;p&gt;I migrated this site to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.getzola.org/&quot;&gt;Zola&lt;/a&gt; 0.23, released yesterday with the new &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://keats.github.io/tera/&quot;&gt;Tera 2&lt;/a&gt; template engine (Well, 0.23.1 from today actually). When I &lt;a href=&quot;/blog/a-new-version-of-the-site-for-2026-in-zola/&quot;&gt;chose Zola&lt;/a&gt; last March, I praised its creator for not chasing the latest fad. I stand by it: 0.23 breaks my templates, but it does it in a cleaner way.&lt;/p&gt;
&lt;p&gt;Tera 2 removes the old macros and imports, and Zola 0.23 removes the shortcodes. Everything is now a namespaced &lt;strong&gt;component&lt;/strong&gt;. A macro that I used to import and call like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% import &amp;quot;macros.html&amp;quot; as utils %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% macro show_link(url) %}&amp;lt;a href=&amp;quot;{{ url }}&amp;quot;&amp;gt;{{ url }}&amp;lt;/a&amp;gt;{% endmacro %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{ utils::show_link(url=link) }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is now a global component with no import at all:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% component site.show_link(url) %}&amp;lt;a href=&amp;quot;{{ url }}&amp;quot;&amp;gt;{{ url }}&amp;lt;/a&amp;gt;{% endcomponent %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{&amp;lt;site.show_link url={link} /&amp;gt;}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The big philosophical change: components are global and no longer inherit the caller context. Every variable — &lt;code&gt;page&lt;/code&gt;, &lt;code&gt;section&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;current_path&lt;/code&gt; — must be passed explicitly as an argument. More verbose, but it makes dependencies visible. I like that more and more: one way to do it, and it is visible.&lt;/p&gt;
&lt;p&gt;Tera 2 is also &lt;strong&gt;strict&lt;/strong&gt;: a missing variable is now a hard error. My templates use optional chaining (&lt;code&gt;?.&lt;/code&gt;) for anything optional, which catches typos at build time instead of silently rendering broken pages.&lt;/p&gt;
&lt;p&gt;What concretely changed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;concat&lt;/code&gt; and &lt;code&gt;slice&lt;/code&gt; filters are gone → array spread and slicing&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_env&lt;/code&gt; is gone → &lt;code&gt;config.mode == &quot;serve&quot;&lt;/code&gt; for local editor links&lt;/li&gt;
&lt;li&gt;&lt;code&gt;include ... ignore missing&lt;/code&gt; is invalid → empty hook templates&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_page&lt;/code&gt; with &lt;code&gt;fatal=false&lt;/code&gt; → canonical path with &lt;code&gt;lang&lt;/code&gt; and &lt;code&gt;allow_missing=true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_taxonomy_url&lt;/code&gt; with &lt;code&gt;name&lt;/code&gt; → &lt;code&gt;term&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/keats/tera/blob/master/MIGRATION.md&quot;&gt;migration guide&lt;/a&gt; was my best map through all of this.&lt;/p&gt;
&lt;p&gt;I use the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.getzola.org/themes/apollo/&quot;&gt;Apollo&lt;/a&gt; theme as a git submodule, and as it does not support Zola 0.23 yet, I keep a small local template-only patch of it until upstream migrates. The design, CSS, and JavaScript are untouched: this was a syntax migration, not a redesign, and I did not rewrite my post contents either.&lt;/p&gt;
&lt;h2 id=&quot;use-of-ai&quot;&gt;Use of AI&lt;a class=&quot;zola-anchor&quot; href=&quot;#use-of-ai&quot; aria-label=&quot;Anchor link for: use-of-ai&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I chose to have AI help me migrate my site. It worked flawlessly, so I encourage you to do the same. AI work especially well with Zola, as it is opinionated, and that means that there are clear ways of doing things so that AI agents do not get lost in rabbit holes trying to pursue all the possibilities of more flexible systems like Hugo.&lt;/p&gt;
&lt;p&gt;For reference here is the first prompt I gave it to prepare the plan for the migration:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;I want you to only create a document for agents ai/agents/tera2.md to summarize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;how tera2 of Zola 0.23 differs from tera1 of Zola 0.22, and the plan to migrate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my site from Zola 0.23 to 0.22.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Examine the differences between Zola 0.22 and 0.23, not just tera.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Docs:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tera2 https://keats.github.io/tera/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Migration guide Tera1 → Tera2 https://github.com/Keats/tera/blob/master/MIGRATION.md&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Zola 0.23 docs https://www.getzola.org/documentation/getting-started/overview/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Take your time, be thourough, but do not modify yet any file of my site except&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;the ones in ai/agents/ and AGENTS.md&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Then, plan the migration of this site to zola 0.23&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1. not modifying the contents of the posts unless necessary for tera2 changes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2. not changing the look and feel, the UI of the site&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3. adapting the various templates&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4. changing my local copy of the Apollo theme I use if needed.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   These changes are a stopgap measure until upstream apollo is migrated to Zola 0.23&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I use Deepseek v4 flash normally, but chose to use GPT-5.6 Luna for this migration as it is currently quite cheap and I trust it more to not go change unecessary files. And Deepseek as no vision, so it cannot check the actual visual results of changes. It helped me greatly for this migration, without any problems.&lt;/p&gt;
&lt;h3 id=&quot;summary-of-ai-actions&quot;&gt;Summary of AI actions:&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary-of-ai-actions&quot; aria-label=&quot;Anchor link for: summary-of-ai-actions&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Replaced Tera 1 macros, imports, &lt;code&gt;self::&lt;/code&gt; calls, and macro namespaces with
namespaced Tera 2 components in the root templates and Apollo templates.&lt;/li&gt;
&lt;li&gt;Converted the local language-listing, page, navigation, debug, file
inclusion, and section-name helpers to components.&lt;/li&gt;
&lt;li&gt;Converted the site shortcode implementations to components in
&lt;code&gt;templates/macros/shortcodes.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Converted active post calls from the removed Zola shortcode syntax to Tera 2
component syntax. This includes YouTube, snapshots, attachments, Mermaid,
static-file inclusion, legacy overlays, obsolete notices, and SVG icons.&lt;/li&gt;
&lt;li&gt;Passed explicit &lt;code&gt;base_path&lt;/code&gt; values to components that used to receive
&lt;code&gt;page.path&lt;/code&gt; implicitly from Zola shortcodes.&lt;/li&gt;
&lt;li&gt;Updated &lt;code&gt;get_page&lt;/code&gt; calls to use the canonical path with &lt;code&gt;lang=&quot;fr&quot;&lt;/code&gt; and
&lt;code&gt;allow_missing=true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Updated &lt;code&gt;get_taxonomy_url&lt;/code&gt; calls from &lt;code&gt;name&lt;/code&gt; to &lt;code&gt;term&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Replaced the removed &lt;code&gt;get_env&lt;/code&gt; call with &lt;code&gt;config.mode == &quot;serve&quot;&lt;/code&gt; for the
local editor links.&lt;/li&gt;
&lt;li&gt;Replaced the removed &lt;code&gt;concat&lt;/code&gt; and &lt;code&gt;slice&lt;/code&gt; filters with Tera 2 array spread
and slicing, and changed the &lt;code&gt;object&lt;/code&gt; test to &lt;code&gt;map&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Added empty Apollo hook templates because Tera 2 no longer accepts
&lt;code&gt;include ... ignore missing&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Updated &lt;code&gt;dev/bin/site-check&lt;/code&gt; to recognize the new legacy component syntax.&lt;/li&gt;
&lt;li&gt;Updated &lt;code&gt;static/ZOLA&lt;/code&gt; to &lt;code&gt;zola 0.23.0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>PDP: Publish, Don&#39;t Perish</title>
        <published>2026-08-02T00:00:00+00:00</published>
        <updated>2026-08-02T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/pdp-publish-dont-perish/"/>
        <id>https://colas.nahaboo.net/blog/pdp-publish-dont-perish/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/pdp-publish-dont-perish/">&lt;p&gt;I stumbled recently upon &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://elizabethtai.com/2023/07/02/posse-and-pesos-better-ways-to-publish-content/&quot;&gt;Elizabeth Tai&#39;s POSSE and PESOS definitions&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;POSSE&lt;/strong&gt;: Publish (on your) Own Site, Syndicate Elsewhere&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PESOS&lt;/strong&gt;: Publish Elsewhere, Syndicate to Own Site&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which prompted me to think that after a first POSSE phase, toying with the emerging web landcape, I was doing mostly PESOS as I found that posting in topic-specific forums made reaching an audience much easier. But after some time, after seeing forums disappear suddenly, I began to POSSE-collect my scattered PESOS posts.&lt;/p&gt;
&lt;p&gt;But now at 66, I am more and more focused on &lt;strong&gt;PDP: Publish, Don&#39;t Perish!&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why&quot; aria-label=&quot;Anchor link for: why&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;POSSE and PESOS answer the question &lt;em&gt;where&lt;/em&gt; you publish. They say nothing about the one that worries me most at my age: &lt;em&gt;will what you published still be there when you are not?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The whole &quot;own your content&quot; movement assumes you will be around to keep owning it — to renew the domain, to pay the host, to answer the support tickets. But at 66, I am starting to think more about the opposite assumption: what happens to all this when I cannot maintain it anymore?&lt;/p&gt;
&lt;h2 id=&quot;what&quot;&gt;What?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what&quot; aria-label=&quot;Anchor link for: what&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I started applying PDP years before I gave it a name. Five years ago, in &lt;a href=&quot;/blog/one-year-retired&quot;&gt;one year retired&lt;/a&gt; I wrote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It may sound ridiculous, but at now 61, setting things up so they do not disappear when I do is becoming an important consideration. I will thus progressively stop using self-hosted sites to publish on places that will survive me, as nobody in my family is tech-savvy enough to maintain a web site.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That was the switch from mercurial to git, and &lt;a href=&quot;/code/moving-to-github/&quot;&gt;moving to GitHub&lt;/a&gt;. As we say in France, &quot;the graveyards are full of indispensable men.&quot;&lt;/p&gt;
&lt;p&gt;So, as a pun on the famous saying &lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Publish_or_perish&quot;&gt;Publish or Perish&lt;/a&gt;&lt;/strong&gt; I decided to call it &lt;strong&gt;PDP: Publish, Don&#39;t Perish!&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how&quot;&gt;How?&lt;a class=&quot;zola-anchor&quot; href=&quot;#how&quot; aria-label=&quot;Anchor link for: how&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Over the years I have refined this into a simple triage: separate my content by how much I need it to survive me.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Transient&lt;/strong&gt; — thoughts, rants, day-to-day musings. Keep them on this own self-hosted site. If it dies, no great loss.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For the family&lt;/strong&gt; — photos, memories, things your children will want. Put them somewhere that outlives you and easy to use for non-technical wife and chidren, even if it costs a bit: this is where paying a reliable host is worth it. I use a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://docs.hetzner.com/storage/storage-box/&quot;&gt;Hetzner Box&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Perennial&lt;/strong&gt; — code, hard-won knowledge, things the world might still want in 50 years. This goes into git repositories that I can thus move easily to git platorms that are the most probable to survive me, GitHub for now. I don&#39;t use facny GitHub features, to make moving or copying these repository as simple as possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And there is now a new, unexpected ally in the perennial column: &lt;strong&gt;AI&lt;/strong&gt;. Even if I never get a single visitor on my pages on this site, I know that publishing on a perennial platform means my code will be ingested by AI assistants and become a tiny — very tiny — part of humanity&#39;s collective knowledge. I have no illusion that my contribution is a major one, but there is something quietly satisfying in the thought that my bash snippets will be digested forever by some distant neural network. The graveyards may be full of indispensable men, but their code lives on in the training data.&lt;/p&gt;
&lt;h2 id=&quot;am-i-reinventing-the-wheel&quot;&gt;Am I reinventing the wheel?&lt;a class=&quot;zola-anchor&quot; href=&quot;#am-i-reinventing-the-wheel&quot; aria-label=&quot;Anchor link for: am-i-reinventing-the-wheel&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I did a bit of homework, and the honest answer is: &lt;strong&gt;no, the idea is not new.&lt;/strong&gt; There is a whole movement around it, I just did not know the name.&lt;/p&gt;
&lt;p&gt;The IndieWeb community has called it the &lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://indieweb.org/longevity&quot;&gt;Long Web&lt;/a&gt;&lt;/strong&gt; for years, a concept &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://adactio.com/articles/1522/&quot;&gt;Jeremy Keith articulated in 2008&lt;/a&gt;: the qualities that make a format good for the long term — simplicity, openness, standardisation — are the same qualities that make it good practice today. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://brennan.day/how-are-we-preparing-for-the-long-web/&quot;&gt;Brennan Brown&#39;s recent essay&lt;/a&gt; is the best modern treatment: the stats are sobering (a quarter of the web&#39;s pages from a decade ago are gone, two-thirds of links rot), and the conclusion is that the IndieWeb is accidentally a preservation ethic.&lt;/p&gt;
&lt;p&gt;There is also &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://jeffhuang.com/designed_to_last/&quot;&gt;Jeff Huang&#39;s &quot;This Page is Designed to Last&quot;&lt;/a&gt;, a practical manifesto for building sites that survive 10 to 30 years — vanilla HTML, no hotlinking, static over dynamic. Much of what I did with this very site (plain Markdown files, no database, an SSG that outputs static pages) aligns with it, and the &lt;a href=&quot;/blog/a-new-version-of-the-site-for-2026-in-zola&quot;&gt;migration to Zola in 2026&lt;/a&gt; was done with exactly these concerns in mind.&lt;/p&gt;
&lt;p&gt;And if you want someone else to do it for you, the market exists: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://posthaven.com/&quot;&gt;Posthaven&lt;/a&gt; promised to never shut down, and WordPress.com now sells a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://wordpress.com/blog/2025/02/12/100-year-domains-plans/&quot;&gt;100-Year Plan&lt;/a&gt; — $38,000 to keep your site online for a century. I wish them well, but it does raise the obvious question: what happens to the plan if Automattic itself does not make it to 2125?&lt;/p&gt;
&lt;p&gt;So where does that leave PDP? I see it as the lazy man&#39;s version of all this. The Long Web is a movement, Jeff Huang&#39;s page is a manifesto, the 100-Year Plan is a product. PDP is just a reminder, for people like me who do not want to pay $38,000 or join a movement: &lt;em&gt;choose your formats and your hosts with an eye on outliving you, and the rest takes care of itself.&lt;/em&gt; The good news is that the &quot;correct&quot; choice is also the simple one: plain files, open formats, and a host bigger than you are.&lt;/p&gt;
&lt;p&gt;POSSE and PESOS assume you will be there to keep your site alive. PDP is for those of us who know we will not. :-)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Related thoughts: my &lt;a href=&quot;/blog/go-single-binary-fanatic&quot;&gt;single-binary fanaticism&lt;/a&gt; is the same reflex applied to code; the &lt;a href=&quot;/blog/a-new-version-of-the-site-for-2026-in-zola&quot;&gt;2026 Zola migration&lt;/a&gt; and &lt;a href=&quot;/code/moving-to-github/&quot;&gt;moving to GitHub&lt;/a&gt; were PDP before I had the name.&lt;/em&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Fanatic of the single self-contained executable</title>
        <published>2026-07-31T00:00:00+00:00</published>
        <updated>2026-07-31T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/go-single-binary-fanatic/"/>
        <id>https://colas.nahaboo.net/blog/go-single-binary-fanatic/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/go-single-binary-fanatic/">&lt;p&gt;I am becoming more and more a fanatic of the single self-contained executable, with no runtime dependencies, that Go provides: one binary, forever. No npm, virtualenv, docker, flatpak, snap... no version hell.&lt;/p&gt;
&lt;p&gt;The qualities I lived with and took for granted during my years of coding in C and shell.&lt;/p&gt;
&lt;p&gt;To the point that when I find now a python/node/java/ruby/php piece of software I would like to install, my first reflex is to just recode the darn thing in Go. I know, I know, rewriting a perfectly working piece of software just to avoid a dependency is bordering on insanity, but the result is so satisfying... A single file that will still run in 20 years, with no upgrades, no breakage, no maintenance.&lt;/p&gt;
&lt;p&gt;And with AI, now, it is becoming less and less insane!&lt;/p&gt;
&lt;p&gt;(&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/colas.nahaboo.net/post/3mrxclxl64s2e&quot;&gt;Bluepost &lt;img src=&#39;/icon/social/bluesky-blue.svg&#39;&gt;&lt;/a&gt;)&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why is the US the only country to write dates as MM/DD/YYYY</title>
        <published>2026-06-09T00:00:00+00:00</published>
        <updated>2026-06-09T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/why-is-the-us-the-only-country-to-write-dates-as-mm-dd-yyyy/"/>
        <id>https://colas.nahaboo.net/blog/why-is-the-us-the-only-country-to-write-dates-as-mm-dd-yyyy/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/why-is-the-us-the-only-country-to-write-dates-as-mm-dd-yyyy/">&lt;p&gt;In short: &lt;strong&gt;chance&lt;/strong&gt;, followed by &lt;strong&gt;isolation&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Before the late 19th century, there was no international standard for writing dates. In both Great Britain and the American colonies, people used two formats interchangeably.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You could write &lt;strong&gt;Month-Day-Year&lt;/strong&gt; (e.g., &quot;October 31st, 1776&quot;), which matched the spoken phrase &quot;October 31st.&quot;&lt;/li&gt;
&lt;li&gt;Or, you could write &lt;strong&gt;Day-Month-Year&lt;/strong&gt; (e.g., &quot;the 31st of October, 1776&quot;), matching the spoken phrase &quot;the 31st of October.&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because the British Empire colonized America during a period when Month-Day-Year happened to be incredibly common, early Americans adopted it as their standard format.&lt;/p&gt;
&lt;p&gt;However, during the late 19th and early 20th centuries, global trade, international shipping, and telegraph networks expanded. Great Britain sought to standardize its systems to align with continental Europe, which favored the Day/Month/Year format because it is strictly logical and hierarchical.&lt;/p&gt;
&lt;p&gt;Ultimately, while Britain altered its habits to match Europe, the United States remained geographically isolated across the Atlantic and saw no pressing economic reason to change. The exact same thing happened with the adoption of the Imperial system (feet versus meters).&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>I recovered my Facebook account, read how</title>
        <published>2026-04-28T00:00:00+00:00</published>
        <updated>2026-04-28T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/i-recovered-my-facebook-account-read-how/"/>
        <id>https://colas.nahaboo.net/blog/i-recovered-my-facebook-account-read-how/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/i-recovered-my-facebook-account-read-how/">&lt;h2 id=&quot;what-happened&quot;&gt;What happened&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-happened&quot; aria-label=&quot;Anchor link for: what-happened&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On 2024-10-24, &lt;a href=&quot;https://colas.nahaboo.net/blog/my-facebook-account-has-changed-hacked/&quot;&gt;my Facebook account was hacked&lt;/a&gt;. Alas, Facebook did not allow me to get back my account, or even report the account as compromised, without entering the current password that whad been changed by the hackers. So I had to create a new account, and moved on.&lt;/p&gt;
&lt;p&gt;However, I recently created a test account on Instagram, to try to generate RSS feeds to follow Instagram accounts more comfortably via my RSS-Bridge. And I was surprised to see that my &quot;new&quot; account was in fact the account of another user that had been blocked, then unblocked.&lt;/p&gt;
&lt;p&gt;This prompted me to try to re-log into my old Facebook account and... it worked! &lt;strong&gt;I was able to reset the password&lt;/strong&gt; without knowing the current one.
I thus will remove the new account after some time.&lt;/p&gt;
&lt;h2 id=&quot;nice-but-why&quot;&gt;Nice, but why?&lt;a class=&quot;zola-anchor&quot; href=&quot;#nice-but-why&quot; aria-label=&quot;Anchor link for: nice-but-why&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;But looking a bit (for instance about &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://riskbasedauthentication.org/state-of-practice/&quot;&gt;Risk-Based Authentication (RBA)&lt;/a&gt;, it appears I was lucky to try to re-use my account just days after a 6 month delay: Facebook relaxes accounts the security measures 6 months after a detected suspicious activity!&lt;/p&gt;
&lt;p&gt;The behavior I experienced — being blocked from recovery despite having valid contact info, followed by a sudden &quot;opening&quot; of access — is apparently a documented pattern in Facebook’s security ecosystem, notably their &lt;strong&gt;automated risk assessment&lt;/strong&gt; procedures.&lt;/p&gt;
&lt;h3 id=&quot;the-security-freeze-why-i-was-stuck&quot;&gt;The &quot;Security Freeze&quot; (Why I was stuck)&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-security-freeze-why-i-was-stuck&quot; aria-label=&quot;Anchor link for: the-security-freeze-why-i-was-stuck&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When a hijacker changes a password, Facebook’s &quot;Trusted Device&quot; and &quot;Location&quot; protocols often trigger a lock. Even if my email and phone were correct, Facebook may refuse a reset if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I cannot provide the current password, aka &lt;strong&gt;The &quot;Current Password&quot; Requirement&lt;/strong&gt;. This is a common defensive measure when Facebook detects a &quot;conflict of ownership.&quot; If the system sees two different locations (mine and the hacker&#39;s) trying to claim the account, it often demands the &lt;em&gt;current&lt;/em&gt; password to prevent the owner from being &quot;kicked out&quot; by someone who isn&#39;t actually the owner. Needless to say, this is a really bad design, as hackers first move is to change the password.&lt;/li&gt;
&lt;li&gt;I use another browser. As I tried many ways to recover my account, I also tried to use another browser on another machine, to start afresh. But this failed Facebook &lt;strong&gt;IP Reputation&lt;/strong&gt; detection: Seeing I was trying to recover the account from a network or device the system didn&#39;t &quot;trust&quot; at that moment, it applied the most restrictive recovery path to the account.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;why-it-suddenly-worked-the-6-months-cooldown-period&quot;&gt;Why it suddenly worked (The 6 months &quot;Cooldown&quot; Period)&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-it-suddenly-worked-the-6-months-cooldown-period&quot; aria-label=&quot;Anchor link for: why-it-suddenly-worked-the-6-months-cooldown-period&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Nothing is actually officially documented, but here is the likely scenario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Risk Score Decay:&lt;/strong&gt; After 6 months of inactivity (or if the hacker eventually triggered a &quot;Security Lock&quot; that made the account go dormant), the &quot;Risk Score&quot; associated with the account drops.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Account Dormancy:&lt;/strong&gt; Facebook often flags accounts that have been compromised as &quot;checkpointed.&quot; After a certain period of time without successful logins from the hijacker, the system may lower the threshold for recovery for the &lt;em&gt;original&lt;/em&gt; owner, especially if he are using a device or IP address that was associated with the account for years before the hack.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The &quot;Verification Reset&quot;:&lt;/strong&gt; Facebook occasionally clears the &quot;verification debt&quot; on accounts. If the hacker was blocked by Facebook’s automated systems (e.g., for spamming), the account enters a state where the next person to provide valid 2FA or email confirmation is granted access without the &quot;current password&quot; hurdle.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of this is totally automated, with no human intervention, by the system&#39;s &lt;strong&gt;&quot;Identity Verification&quot;&lt;/strong&gt; logic resetting itself after a period of dormancy. Once the &quot;Pirate&quot; was no longer active, the system stopped viewing my recovery attempt as a &quot;hostile takeover&quot; and allowed the standard email/phone reset to work.&lt;/p&gt;
&lt;h3 id=&quot;summary-of-known-behavior&quot;&gt;Summary of Known Behavior&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary-of-known-behavior&quot; aria-label=&quot;Anchor link for: summary-of-known-behavior&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Stage&lt;/th&gt;&lt;th style=&quot;text-align: left&quot;&gt;System Logic&lt;/th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Result&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Initial Hack&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;High-conflict state; system protects the &quot;active&quot; user.&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Recovery denied despite valid email.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;The 6-Month Gap&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Account goes dormant or hacker is &quot;checkpointed.&quot;&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Security tension on the account relaxes.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Recovery&lt;/strong&gt;&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;System recognizes you are the owner IP/Location and valid contact info.&lt;/td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Password reset allowed without &quot;Current Password.&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;what-to-do-once-the-account-is-recovered&quot;&gt;What to do once the account is recovered&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-to-do-once-the-account-is-recovered&quot; aria-label=&quot;Anchor link for: what-to-do-once-the-account-is-recovered&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Check the Settings for &lt;strong&gt;&quot;Saved Login&quot;&lt;/strong&gt;, &lt;strong&gt;&quot;Where you&#39;re logged in&quot;&lt;/strong&gt;, and &lt;strong&gt;&quot;Apps and websites&quot;&lt;/strong&gt; immediately. Sometimes hackers leave a &quot;backdoor&quot; by authorizing a specific browser or app that doesn&#39;t require a password.&lt;/li&gt;
&lt;li&gt;Change the password, enable 2FA (Two-factor authentication).&lt;/li&gt;
&lt;li&gt;Remove all apps connected to the account.&lt;/li&gt;
&lt;li&gt;Check other sites that authorized logins from this Facebook account, change their passwords andf look for suspicious activity.&lt;/li&gt;
&lt;/ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Numéros de telephone arnaques</title>
        <published>2026-04-13T00:00:00+00:00</published>
        <updated>2026-04-13T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/numeros-de-telephone-arnaques/"/>
        <id>https://colas.nahaboo.net/blog/numeros-de-telephone-arnaques/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/numeros-de-telephone-arnaques/">&lt;p&gt;&lt;strong&gt;Attention arnaque:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Le No de tel &lt;strong&gt;0189628604&lt;/strong&gt; vous appelle en se faisant passer pour un conseiller bancaire (AXA), en ayant votre nom, adresse, en prétendant avoir remarqué des tentatives de paiement répétées depuis Amazon.&lt;/p&gt;
&lt;p&gt;C&#39;est une arnaque. J&#39;ai raccroché de suite et appelé AXA pour vérifier.&lt;/p&gt;
&lt;p&gt;La conseillère nous a d&#39;ailleurs dit que elle-même avait failli se faire avoir récemment (un faux appel de sa mutuelle).&lt;/p&gt;
&lt;p&gt;Je fais ce post simplement pour mettre 0189628604 (ou 33 189628604 ou 01 89 62 86 04) sur le web pour que une recherche de ce No tombe sur ce message.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A new version of the site for 2026, in Zola</title>
        <published>2026-03-19T00:00:00+00:00</published>
        <updated>2026-03-22T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2026-in-zola/"/>
        <id>https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2026-in-zola/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2026-in-zola/">&lt;p&gt;I &lt;a href=&quot;/blog/a-new-version-of-the-site-for-2021&quot;&gt;said&lt;/a&gt; that I wanted to migrate this web site to a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Static_site_generator&quot;&gt;SSG&lt;/a&gt; (Static Site Generator).
And, after 5 years of procrastination, Ta-Da! here is the new site!&lt;/p&gt;
&lt;p&gt;Initially, I was planning to use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;, since I love coding in Go, and was not planning to learn Rust (Hugo is coded in Go and Zola in Rust), but I finally chose &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.getzola.org/&quot;&gt;Zola&lt;/a&gt; over Hugo for many reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zola has basically all the performance advantages of Hugo, and is also a single binary, with no need for databases, docker, snap, flatpak...&lt;/li&gt;
&lt;li&gt;Zola is &lt;strong&gt;opinionated&lt;/strong&gt;. This is very important for me, I love more and more the systems were there is &quot;only one way to do it&quot;. Needless to say, I hate perl, and I love Go.&lt;/li&gt;
&lt;li&gt;Zola is stable, and its creator (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/keats&quot;&gt;&quot;Keats&quot;&lt;/a&gt;) very committed to not chasing the latest fad. This means less risk of an upgrade breaking things.&lt;/li&gt;
&lt;li&gt;Zola template engine, Tera, is both more powerful and more readable than the standard Go template engine used by Hugo.&lt;/li&gt;
&lt;li&gt;Zola comes with more useful built-in features, but no plugins that in my opinion brings complexity, especially in docs, and upgrade hell.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As for the theme, I was looking for a clean responsive modern simple theme, with high scores in the various web performance benchmarks, with search and comments, and some support for multilingual (the site is in English with a few pages also translated in French). I tried the two leaders in the Zola theme ecosystem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.getzola.org/themes/tabi/&quot;&gt;Tabi&lt;/a&gt; I liked the looks but it felt a bit too complex for my needs: as a Zola novice I was afraid to end up relying too much on Tabi-specific feature instead of pure Zola and CSS ones.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.getzola.org/themes/abridge/&quot;&gt;ABridge&lt;/a&gt; I liked the architecture, not so much the design, but I struggled to make it work, it seems the doc still advise settings that break on recent Zola versions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I thus looked for a simpler theme, and chose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.getzola.org/themes/apollo/&quot;&gt;Apollo&lt;/a&gt; which was perfect for my needs, and simple enough to be easily modified for any of my future needs. I also enabled its support for the  &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://giscus.app/&quot;&gt;Giscus&lt;/a&gt; commenting system.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Porting my contents was made easy because I had anticipated this migration, and used Markdown for my posts in the Foswiki engine, instead of the native Foswiki syntax. So converting was basically adding a frontmatter to the pages, and fixing some links. I converted older posts with pandoc.&lt;/p&gt;
&lt;p&gt;I have made a quick first migration. I will continue working on the CSS architecture and the looks in the following weeks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; on 2026-03-22: I now am satisfied of the result. I plan to work a bit more to add a search for only the French pages (now the search ignores them), autodetection of the browser light/dark preferences, sort the tags alphabetically in the page info line.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mon compte Facebook a changé (piraté)</title>
        <published>2024-10-24T00:00:00+00:00</published>
        <updated>2024-10-24T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/my-facebook-account-has-changed-hacked-fr/"/>
        <id>https://colas.nahaboo.net/blog/my-facebook-account-has-changed-hacked-fr/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/my-facebook-account-has-changed-hacked-fr/">&lt;div class=&quot;obsolete-overlay&quot;&gt;
    OBSOLETE
&lt;/div&gt;
&lt;style&gt;
.obsolete-overlay {
    position: fixed;
    top: 45%;
    left: 35%;
    transform: translate(-50%, -50%) rotate(-45deg);
    font-size: 12vw;
    font-weight: 900;
    color: rgba(255, 0, 0, 0.4);
    background: rgba(255, 255, 0, 0.2);
    border: 15px solid rgba(255, 0, 0, 0.3);
    padding: 20px 50px;
    z-index: 9999;
    pointer-events: none;
    text-transform: uppercase;
    white-space: nowrap;
    user-select: none;
}
&lt;/style&gt;
&lt;div class=&#39;info warning&#39;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; height=&quot;24px&quot; viewBox=&quot;0 -960 960 960&quot; width=&quot;24px&quot; fill=&quot;#1f1f1f&quot;&gt;&lt;path d=&quot;M449.5-85Q435-91 423-102L102-423q-11-12-17-26.5T79-480q0-16 6-31t17-26l321-321q12-12 26.5-17.5T480-881q16 0 31 5.5t26 17.5l321 321q12 11 17.5 26t5.5 31q0 16-5.5 30.5T858-423L537-102q-11 11-26 17t-31 6q-16 0-30.5-6Zm30.5-74 321-321-321-321-321 321 321 321Zm-40-281h80v-240h-80v240Zm68.5 108.5Q520-343 520-360t-11.5-28.5Q497-400 480-400t-28.5 11.5Q440-377 440-360t11.5 28.5Q463-320 480-320t28.5-11.5ZM480-480Z&quot;/&gt;&lt;/svg&gt; Warning: obsoleted by &lt;a href=&#39;/blog/i-recovered-my-facebook-account-read-how/&#39;&gt;this new version&lt;/a&gt;.&lt;/div&gt;
&lt;p&gt;Attention : le 2024-10-24, mon compte Facebook a été piraté. Hélas, Facebook ne m&#39;a pas permis de récupérer mon compte, ni même de le signaler, et j&#39;ai donc dû en créer un nouveau.&lt;/p&gt;
&lt;p&gt;Je vous prie donc de ne plus utiliser mon ancien compte ( https://www.facebook.com/colas.nahaboo ) et de le bloquer sur Facebook pour être sûr, car les pirates vont l&#39;utiliser pour pirater et hameçonner d&#39;autres personnes, et d&#39;utiliser mon nouveau compte: https://www.facebook.com/profile.php?id=61567836084230.&lt;/p&gt;
&lt;p&gt;J&#39;ai changé ma photo de profil (sur Facebook uniquement pour l&#39;instant) pour différencier les deux comptes :&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/my-facebook-account-has-changed-hacked/Avatars-old-new.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My Facebook account has changed (hacked)</title>
        <published>2024-10-24T00:00:00+00:00</published>
        <updated>2024-10-24T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/my-facebook-account-has-changed-hacked/"/>
        <id>https://colas.nahaboo.net/blog/my-facebook-account-has-changed-hacked/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/my-facebook-account-has-changed-hacked/">&lt;div class=&quot;obsolete-overlay&quot;&gt;
    OBSOLETE
&lt;/div&gt;
&lt;style&gt;
.obsolete-overlay {
    position: fixed;
    top: 45%;
    left: 35%;
    transform: translate(-50%, -50%) rotate(-45deg);
    font-size: 12vw;
    font-weight: 900;
    color: rgba(255, 0, 0, 0.4);
    background: rgba(255, 255, 0, 0.2);
    border: 15px solid rgba(255, 0, 0, 0.3);
    padding: 20px 50px;
    z-index: 9999;
    pointer-events: none;
    text-transform: uppercase;
    white-space: nowrap;
    user-select: none;
}
&lt;/style&gt;
&lt;div class=&#39;info warning&#39;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; height=&quot;24px&quot; viewBox=&quot;0 -960 960 960&quot; width=&quot;24px&quot; fill=&quot;#1f1f1f&quot;&gt;&lt;path d=&quot;M449.5-85Q435-91 423-102L102-423q-11-12-17-26.5T79-480q0-16 6-31t17-26l321-321q12-12 26.5-17.5T480-881q16 0 31 5.5t26 17.5l321 321q12 11 17.5 26t5.5 31q0 16-5.5 30.5T858-423L537-102q-11 11-26 17t-31 6q-16 0-30.5-6Zm30.5-74 321-321-321-321-321 321 321 321Zm-40-281h80v-240h-80v240Zm68.5 108.5Q520-343 520-360t-11.5-28.5Q497-400 480-400t-28.5 11.5Q440-377 440-360t11.5 28.5Q463-320 480-320t28.5-11.5ZM480-480Z&quot;/&gt;&lt;/svg&gt; Warning: obsoleted by &lt;a href=&#39;/blog/i-recovered-my-facebook-account-read-how/&#39;&gt;this new version&lt;/a&gt;.&lt;/div&gt;
&lt;p&gt;Warning: on 2024-10-24, my Facebook account was hacked. Alas, Facebook did not allow me to get back my account, or even report it, so I had to create a new one.&lt;/p&gt;
&lt;p&gt;So please never use my old account anymore ( https://www.facebook.com/colas.nahaboo ) and block it under Facebook to be safe, as hackers are going to use it to hack and phish others, and use my new account: https://www.facebook.com/profile.php?id=61567836084230&lt;/p&gt;
&lt;p&gt;I changed my profile picture (on Facebook only for now) to differentiate the two accounts:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://colas.nahaboo.net/blog/my-facebook-account-has-changed-hacked/Avatars-old-new.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>One year retired</title>
        <published>2022-02-24T00:00:00+00:00</published>
        <updated>2022-02-24T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/one-year-retired/"/>
        <id>https://colas.nahaboo.net/blog/one-year-retired/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/one-year-retired/">&lt;p&gt;I have been retired for one year now, and what happened? Well...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I basically stopped coding and reading about anything computer-related for eight months. I didn&#39;t expect it, I was thinking I would start coding at once, going through my huge todo list of various projects.&lt;/li&gt;
&lt;li&gt;I enjoyed being able to go SUP surfing at will, but I ended up actually less on the water than before, simply because i didn&#39;t feel pressured into going on the water if the conditions were not enjoyable: I have now all the time in the world, I can wait for better conditions.&lt;/li&gt;
&lt;li&gt;I started what I should have done years ago: Stretching at least 30 minutes daily, and warming up a full 10 minutes before going surfing. Work and play for me were mainly sitting in front of a computer, and I had become awfully stiff. I will detail my routine in later posts, it is worth it.&lt;/li&gt;
&lt;li&gt;I dived deep in modern physics: astrophysics, cosmology and quantum mechanics. This also will warrant a full separate post.&lt;/li&gt;
&lt;li&gt;I started re-coding in the last four months:
&lt;ul&gt;
&lt;li&gt;The first month I began working on various bits of code (shell scripts), progressively getting back to speed, and also deciding to learn the language Go. I was looking for a very longtime for an efficient language to replace lisp or C as compliment to scripting (I never liked Java), and was hesitating between Rust and Go. A discussion with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.arsac.org/olivier/&quot;&gt;Olivier Arsac&lt;/a&gt; convinced me to try Go.&lt;/li&gt;
&lt;li&gt;I switched to git (I was using mercurial) for version control, and &lt;a href=&quot;/code/moving-to-github/&quot;&gt;moved&lt;/a&gt; my publicly available source codes from my personal web site to my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ColasNahaboo&quot;&gt;GitHub&lt;/a&gt;. It may sound ridiculous, but at now 61, setting things up so they do not disappear when I do is becoming an important consideration. I will thus progressively stop using self-hosted sites to publish on places that will survive me, as nobody in my family is tech-savvy enough to maintain a web site.&lt;/li&gt;
&lt;li&gt;Then in December I stumbled upon the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://adventofcode.com/&quot;&gt;Advent of Code&lt;/a&gt; challenge that I decided to do in bash for the challenge, and it was unexpectedly productive? I learned more in these 25 puzzles than in my last 10 years of professional bash scripting. You can see my solutions in my post &lt;a href=&quot;/code/bash-lessons-learned-with-aoc-2021&quot;&gt;Bash lessons learned with AoC 2021&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Thus, after finishing the Go tutorial, I decided to do the previous AoC years in Go. And I just &lt;a href=&quot;/code/completed-the-2015-advent-of-code-challenge-in-go&quot;&gt;finished the AoC 2015 in Go&lt;/a&gt;. This definitively made me a Go enthusiast, I realized that the designers of Go had exactly the same opinion of what should be a general programming language: They worshiped readability, simplicity, performance and maintainability while hating inheritance and the feature creep of most modern languages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That was my first year. And now, embarking for the next one!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Pinboard pricing model</title>
        <published>2021-03-01T00:00:00+00:00</published>
        <updated>2021-03-01T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/pinboard-pricing-model/"/>
        <id>https://colas.nahaboo.net/blog/pinboard-pricing-model/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/pinboard-pricing-model/">&lt;p&gt;I am a knowledge addict, and always has been. I was reading as many books as possible, and the advent of the web has been a marvelous gift for me. But I soon realized that I needed some tools to manage this knowledge and supplement my memory. It started with pen and papers, then I used a lot the PDAs (Personal Digital Assistants) such as the fabulous Psion &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Psion_Series_3&quot;&gt;Series 3&lt;/a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Psion_Series_5&quot;&gt;Series 5&lt;/a&gt;, the various smartphones, and finally the bookmarks-in-the-cloud service &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Delicious_(website)&quot;&gt;Delicious&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But as Delicious closed, I searched a replacement, and found &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://pinboard.in/tour/&quot;&gt;Pinboard&lt;/a&gt;, and was hooked. Not only it offered the same functionalities as Delicious (and more), but if was fast and sleek, with a minimal no-nonsense design that I favor.&lt;/p&gt;
&lt;p&gt;It also had an original pricing system: you paid a one-time fee of $0.001 per the number of current users to get access for life. E.g $9.26 if there was already 9263 paying users and you wanted to become the 9264th. The goal was to entice people to register now rather than waiting, even though it may not have scaled. (see &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://leftovertakeout.com/post/3783798631/pinboardin-pricing-model-fixing-their-math&quot;&gt;Pinboard.in Pricing Model: Fixing Their Math&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Alas, it could not be sustained, so in 2015 it adopted a more mainstream yearly fee scheme: $11 / year. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://blog.pinboard.in/2014/12/new_pricing_policy/&quot;&gt;New Pricing Policy (Pinboard Blog)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But we, old timers, kept our lifetime access we bought before the change. We were basically free-riding the new wave of customers...&lt;/p&gt;
&lt;p&gt;Of course it could not go on, so last week, Maciej, the Pinboard author, suggested we voluntarily switch to the yearly fee scheme. And I did it gladly, Pinboard is for me a model of what web sites should be: sleek, fast, and efficient (and not re-selling your private data). At the opposite of the bloated monstrosities that a lot of sites tend to be nowadays.&lt;/p&gt;
&lt;p&gt;Long live Pinboard!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Retired, at last!</title>
        <published>2021-02-25T00:00:00+00:00</published>
        <updated>2021-02-25T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/retired-at-last/"/>
        <id>https://colas.nahaboo.net/blog/retired-at-last/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/retired-at-last/">&lt;p&gt;At last, I am now retired!&lt;/p&gt;
&lt;p&gt;I ceased all activity on 2021-02-17, and my work account will be destroyed on 2021-02-28. A new era of full time surfing, coding and playing opens up. For now it is mostly playing with the new &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.valheimgame.com/&quot;&gt;Valheim&lt;/a&gt; game that is making a huge debut(*), as the waves are not good (winter storms) and I take a (small) coding break.&lt;/p&gt;
&lt;p&gt;I will try to make a post per week on this site, starting now 2021-03-01. I know there is no way I will be able to keep the rhythm, but let&#39;s say it should be my long-term goal.&lt;/p&gt;
&lt;p&gt;(*) I strongly recommend you read &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://howtomarketagame.com/2021/02/23/valheim-7-lessons-from-their-amazing-marketing/&quot;&gt;# Valheim: 7 marketing lessons from their amazing launch&lt;/a&gt;, which tries to shed some light on its phenomenal success.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A New version of the site for 2021</title>
        <published>2020-12-27T00:00:00+00:00</published>
        <updated>2020-12-27T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2021/"/>
        <id>https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2021/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2021/">&lt;p&gt;A big change is planned for this site in 2021: I am going to abandon the Foswiki engine for it, to pursue my recent goal of going back to the web roots. Basically, it a quest that relies more on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fast rendering&lt;/strong&gt; by no rendering at all: pre-compiling the site pages into static HTML+CSS+JS pages: the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://jamstack.org/&quot;&gt;JAMstack&lt;/a&gt; approach.&lt;/li&gt;
&lt;li&gt;What I call a &lt;strong&gt;LAUW&lt;/strong&gt; approach (&lt;strong&gt;L&lt;/strong&gt;inux &lt;strong&gt;A&lt;/strong&gt;pache &lt;strong&gt;U&lt;/strong&gt;nix-utilities &lt;strong&gt;W&lt;/strong&gt;eb Standards) instead of the traditional &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/LAMP_(software_bundle)&quot;&gt;LAMP&lt;/a&gt;. Using the full strengths of Linux, Apache, the GNU Unix utilities, and the modern web standards (HTML5, CSS4, JS ES6) now that Internet Explorer is at last dead. This means not using software libraries (e.g: JQuery) and processors (e.g: Saas) that were designed to remedy to the poor state of some browsers.&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;Markdown&lt;/strong&gt; for text editing&lt;/li&gt;
&lt;li&gt;Using ultra &lt;strong&gt;stable and reliable&lt;/strong&gt; technologies. I want to use things that will still work in 10 years, not the fad-of-the-day javascript framework that will be obsolete in 6 months, or that will break compatibility on each update.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Technical&lt;/strong&gt;: And that do not try to be friendly to non-technical authors and admins, as  I will be the sole admin and editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;now&quot;&gt;Now&lt;a class=&quot;zola-anchor&quot; href=&quot;#now&quot; aria-label=&quot;Anchor link for: now&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So now (December 2020), I am still using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://foswiki.org/Home/WebHome&quot;&gt;Foswiki&lt;/a&gt;, but progressively prototyping on it the features I will try to implement later:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A simplified skin, with all the &quot;wiki-ism&quot; (everything editable) removed. As you can see I got rid of the left toolbar, to keep only the top banner with its sections (Code/Surf/Blog) menu on the logo and minimal tools on the right&lt;/li&gt;
&lt;li&gt;Editing contents in Markdown instead of the Foswiki syntax: I now do not use the Foswiki system to edit topics, but desktop-edit via &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://marktext.app/&quot;&gt;marktext&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Having all the post sharing a common Form, so that the fields of this form can be easily converted to YAML as used as frontmatter (metadata) in modern Markdown-based systems.&lt;/li&gt;
&lt;li&gt;But still using all the Foswiki power for the site admin and non-content topics (indexes,...)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The idea is to migrate progressively the contents into a form (Markdown + Frontmatter) usable in a modern static web generator like Hugo, while adapting Foswiki to use this content form, preparing a future migration.&lt;/p&gt;
&lt;p&gt;I have developed the details of what this means in my post on the Foswiki site: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://foswiki.org/Development/FoswikiNonWikiWebSites&quot;&gt;Foswiki for non-wiki web sites&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;spring-2021&quot;&gt;Spring 2021&lt;a class=&quot;zola-anchor&quot; href=&quot;#spring-2021&quot; aria-label=&quot;Anchor link for: spring-2021&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After I retire, at the end of February 2021, I will have more time to ditch Foswiki and implement the site on a new engine. It will probably be a static website generator, most probably &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;, but maybe also &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.getzola.org/&quot;&gt;Zola&lt;/a&gt;  &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;, or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.gatsbyjs.com/&quot;&gt;Gasby&lt;/a&gt;, and incorporating ideas of the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://jamstack.org/generators/&quot;&gt;myriad of other ones&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;summer-2021&quot;&gt;Summer 2021&lt;a class=&quot;zola-anchor&quot; href=&quot;#summer-2021&quot; aria-label=&quot;Anchor link for: summer-2021&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I will then probably replace progressively various components of this system by ones that I will handcraft optimally to incorporate all the ideas I have been toying with during all these years: the HTML+CSS+JS layout, the tag/category system, the search engine, the comment engine, the editing process...&lt;/p&gt;
&lt;h2 id=&quot;later&quot;&gt;Later...&lt;a class=&quot;zola-anchor&quot; href=&quot;#later&quot; aria-label=&quot;Anchor link for: later&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;And I may even at some time create a totally new web engine system, who knows?&lt;/p&gt;
&lt;p&gt;Or code a wiki replacement: a collaborative editing site based on the concepts learned via this experiment.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A New Version of the site for 2020</title>
        <published>2020-07-26T00:00:00+00:00</published>
        <updated>2020-07-26T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2020/"/>
        <id>https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2020/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/a-new-version-of-the-site-for-2020/">&lt;p&gt;After 10 years of
neglect, it is time for a new start of this site, because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I am going to retire in early 2021 (in 6 months), and I will have now time to properly maintain a personal site&lt;/li&gt;
&lt;li&gt;I am feeling the need to archive in a central place all the contents I scatter in various different places, if only for the selfish reason to be able to retreive them more easily&lt;/li&gt;
&lt;li&gt;I was toying with the idea of going to a static web site, as it is now in vogue, and it has a kind of nostalgia for me as I started my web sites as static   sites anyways. But by looking at the existing solutions, I was not convinced by them, as a lot seemed to naively solve the 80% easy part of the problem, and them struggle without any clear vision on how to solve the 20% hard part... a classic situation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I thus decided to keep on using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://foswiki.org&quot;&gt;Foswiki&lt;/a&gt;
(v2.1.6), as it is now quite mature, and thus stable: I like building on
solid, time-tested fundations that will not change every month. And
let&#39;s be honest, it is both extremely powerful and incredibly reliable.
I am just tweaking it for using it as a public site (one author with all
admin rights, and read-only viewers), rather than the standard wiki
setup of many authors, all able to edit contents, with some able to also
admin rights. My postulate is that a dynamic web site like a wiki, with
proper caching, has all the advantages of a static web site, but is more
practical to maintain (although more complex to implement).&lt;/p&gt;
&lt;p&gt;I will detail my views on how to website-ize a wiki in future posts, but
for now, on 2020-07-26 at noon French time, let go live!&lt;/p&gt;
&lt;p&gt;Welcome to my (new) world!&lt;/p&gt;
&lt;p&gt;Colas.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Migration to Foswiki</title>
        <published>2015-10-18T00:00:00+00:00</published>
        <updated>2015-10-18T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/migration-to-foswiki/"/>
        <id>https://colas.nahaboo.net/blog/migration-to-foswiki/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/migration-to-foswiki/">&lt;p&gt;At last, I found the motivation to work again on this site that I have
left dormant since 2009. And I start with a long deserved migration of
the engine from the old TWiki system to the superb Foswiki WIki engine.&lt;/p&gt;
&lt;p&gt;Just installing a new Foswiki, and copying the data seem to provide a
working base, I will then work on fixing the minor bugs and designing a
new look in the following weeks.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Usability issues on a payment form</title>
        <published>2009-03-03T00:00:00+00:00</published>
        <updated>2009-03-03T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/usability-issues-on-a-payment-form/"/>
        <id>https://colas.nahaboo.net/blog/usability-issues-on-a-payment-form/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/usability-issues-on-a-payment-form/">&lt;p&gt;I know, I know, it is easy to nitpick on other people design, but this
morning I tried to pay my phone bill online, and... failed. I had to
retry many times, because I kept making mistakes on a simple,
run-of-the-mill form to enter my credit card data. I was dumbfounded.
How can, in 2009, people manage to make such a trivial and essential
part of online business go so wrong? As I guess you are as curious as
me, here is what I found out: (See the picture for the 3 main pain
points)&lt;/p&gt;
&lt;img src=&quot;telefact-bloopers.png&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1&lt;/strong&gt; the expiration date example is ambiguous: does &lt;code&gt;0903&lt;/code&gt; here means
2009-03 or 2003-09 ? Why didnt they disambiguate it by also adding a
specification (like MMYY, or, as it is a french dialog, MMAA ?)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2&lt;/strong&gt; but today, it was not only ambiguous but plainly misleading! As
we were in March 2009, I assumed that the example was built from the
current month and year. I said cool, so it is YYMM. Wrong! it was
actually the reverse, MMYY, resulting in one failed attempt&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;3&lt;/strong&gt; ok, I filled the fields, and hit the OK button... and it just
reset the page to empty fields! Grumbling, I re-typed the fields,
re-clic, and... another blank page! After these two more failures, I
tried to think (which is what you &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Don&amp;#x27;t_Make_Me_Think&quot;&gt;do not want your users to
do&lt;/a&gt;, trust me). I
then read the button label and discovered that this big, prominent
button alone at the bottom of the page was &lt;strong&gt;not the Submit button&lt;/strong&gt;
but the Cancel one. I should have hit the middle one &quot;Valider&quot;, but
this button was not in the correct place on the flow of the form.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So,after 3 failed attempts, I managed to pay my bill. All this on a
simple form with no fancy verification code or Captcha. Well done
Telefact, I wonder if you can find a worse example still in use today.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What is good code?</title>
        <published>2008-10-22T00:00:00+00:00</published>
        <updated>2008-10-22T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/what-is-good-code/"/>
        <id>https://colas.nahaboo.net/blog/what-is-good-code/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/what-is-good-code/">&lt;p&gt;I stumbled upon the blog post &quot;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://web.archive.org/web/20190630095624/https://weblogs.asp.net/fredriknormen/is-it-important-to-write-good-code&quot;&gt;Is it important to write good
code?&lt;/a&gt;&quot;
the other day, and became more and more ill at ease as I realized that I
thought that I preferred the original code, that the author was trying
to ridicule, over his new &quot;improved&quot; object-oriented version. At first I
guessed this was another manifestation of the the &quot;Worst is best&quot;
scenario - enhancements are often not worth the added complexity - but I
realized that it was perhaps a more profound factor:&lt;/p&gt;
&lt;p&gt;The original code is very good because it ... is &lt;strong&gt;small&lt;/strong&gt;. It fits on a
teminal screen, so an human being can &lt;strong&gt;read&lt;/strong&gt; it at once and have less
items to maintain in his &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two&quot;&gt;short term
memory&lt;/a&gt;
and also &lt;strong&gt;understand&lt;/strong&gt; it easily because it follows a natural way of
thinking with &lt;strong&gt;sentences using IF&lt;/strong&gt;. This becomes obvious by reading
the body of the blog post surrounding the code samples, where you can
see that the author is using phrases such as &quot;if I need this I do that&quot;,
showing that in plain english, the if statement is the best way to make
people understand what you mean. And making code that &lt;strong&gt;people&lt;/strong&gt;
understand is the best way to make debuggable and maintainable code.&lt;/p&gt;
&lt;p&gt;At this moment I noticed the citation in the blog header: &lt;em&gt;&quot;Good
programmers write code that humans can understand&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Indeed :-)&lt;/p&gt;
&lt;p&gt;PS: I know I am a bit exaggerating the issues there, and that I unfairly
nitpick on Fredrik Normé, but it is that it seems to me from my personal
experience that the two changes I see most in my coding efficiency as I
grow older is a decrease of my short term memory capacity, and that I
make more and more typos where I realize I mix up totally words with
totally different meanings but that sound the same, for instance writing
&quot;never&quot; instead of &quot;nether&quot;, making me suspect that our natural way of
thinking may be much more language-based that I imagined...&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mercurial web templating</title>
        <published>2008-10-09T00:00:00+00:00</published>
        <updated>2008-10-09T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/mercurial-web-templating/"/>
        <id>https://colas.nahaboo.net/blog/mercurial-web-templating/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/mercurial-web-templating/">&lt;p&gt;For some time now, I have seen the light and I switched to the new wave
of the Distributed Source Control management systems. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=4XpnKHJAok8&quot;&gt;Linus famous
video&lt;/a&gt; of his Google talk
decided me to try. I was a bit apprehensive at first, wary of engaging
myself on a technology that would bring more problems than solutions,
but after some days of use, the realisation dawned over me: Distributed
Source Control may be one little step for a programmer, but it is a
giant step for programming. Why? because, its &lt;strong&gt;mental model actually
follows your first intuitions&lt;/strong&gt; that most of us developed as young
programmers before using any source control system. Suppose you want to
try a feature? instead of just copying the directory, you clone it. You
mess an operation? you just remove the directory, no embarrassing traces
left to keep the burning scar of shame on you for the following decades
of a central repository. You are used to think of your enhancements as
patches, you can work with patches. I could go on and on, but many
people have done it much better than me so I&#39;ll just say that you should
definitely try it.&lt;/p&gt;
&lt;p&gt;By the way, between the 3 main contenders, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://git-scm.com/&quot;&gt;git&lt;/a&gt;,
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://www.mercurial-scm.org/&quot;&gt;mercurial&lt;/a&gt; (aka HG), and
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/GNU_Bazaar&quot;&gt;bazaar&lt;/a&gt;, I chose mercurial because of its
simplicity, its better support of windows (I work in Linux since 1995
but my coworkers currently use Windows), and because some people at ILOG
started using git so I wanted to be able to try something else. I did
not choose bazaar as I wanted to stay close enough of git, to be able to
switch to it if ever my dream to work in a windows-free world
materializes one day...&lt;/p&gt;
&lt;p&gt;So I started to set up a public web repository of my Open Source personal
work with mercurial, which gave me a simple way to publish my work in
full detail, but, although mercurial is quite easy to use, but I had a
bit of trouble figuring out how to customize its look &amp;amp; feel.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The rebirth of this site</title>
        <published>2008-04-04T00:00:00+00:00</published>
        <updated>2008-04-04T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/the-rebirth-of-this-site/"/>
        <id>https://colas.nahaboo.net/blog/the-rebirth-of-this-site/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/the-rebirth-of-this-site/">&lt;p&gt;At last, I decided myself to redo my old website, which was a collection
of static html and was based on many of the various tools I made in
these past years. As I grew in love with wikis over these years, the
natural tought was just to do it in a Wiki, and naturally in the Wiki I
like the most, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://twiki.org&quot;&gt;TWiki&lt;/a&gt;. So bear with me and keep
posted, as this site will slowly emerge in this first half of 2008.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Browser-history</title>
        <published>2008-03-21T00:00:00+00:00</published>
        <updated>2026-04-25T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/browser-history/"/>
        <id>https://colas.nahaboo.net/blog/browser-history/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/browser-history/">&lt;div class=&quot;obsolete-overlay&quot;&gt;
    Legacy
&lt;/div&gt;
&lt;style&gt;
.obsolete-overlay {
    position: fixed;
    top: 40px;
    left: 60%;
    transform: translate(-50%, -50%) rotate(-5deg);
    font-size: 2vw;
    font-weight: 800;
    color: rgba(255, 0, 0, 0.4);
    background: rgba(255, 255, 0, 0.2);
    border: 15px solid rgba(255, 0, 0, 0.3);
    padding: 10px 20px;
    z-index: 9999;
    pointer-events: none;
    text-transform: uppercase;
    white-space: nowrap;
    user-select: none;
}
&lt;/style&gt;
&lt;p&gt;Browser-history started on February 15, 1996, out of a desire to overcome a Netscape bug: at the time, there was no global history. [Nowadays, in 2026, all browsers have one, of course.] Back then, if you closed a window, its entire history was lost.&lt;/p&gt;
&lt;p&gt;For people visiting many sites, the ability to track where they had been meant they didn&#39;t have to clutter their bookmarks file. If you weren&#39;t sure a site was worth saving, you didn&#39;t have to bookmark it; if you needed it later, you could just browse your history files.&lt;/p&gt;
&lt;p&gt;Later, it occurred to me that this could also be a valuable add-on for people developing experimental browsers [a lot at the time], sparing them from having to build the functionality themselves.&lt;/p&gt;
&lt;p&gt;Browser-history was a small, efficient daemon written in C. Real user services could be built on top of its log files to provide more advanced features, such as graphical representations, advanced search, or collective histories. While it could be seen as a &quot;quick-and-dirty hack&quot; compared to the general solution of using a personal proxy for housekeeping, it was easy to use and it worked.&lt;/p&gt;
&lt;p&gt;I created this legacy page to help people find the archived version of the project, specifically the  &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://web.archive.org/web/20080321182348/https://colas.nahaboo.net/browser-history/&quot;&gt;latest version of 2000-07-20&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The code&lt;/strong&gt; archive itself is &lt;a href=&quot;https://colas.nahaboo.net/blog/browser-history/browser-history-2.8.tgz&quot;&gt;browser-history-2.8.tgz&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is a screenshot of the page:&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;a href=&#39;https://web.archive.org/web/20080321182348/https://colas.nahaboo.net/browser-history/&#39; title=&#39;web archive version&#39;&gt;&lt;img src=&#39;screenshot-page.png&#39;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-manual-page&quot;&gt;The manual page&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-manual-page&quot; aria-label=&quot;Anchor link for: the-manual-page&quot;&gt;🔗&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;name&quot;&gt;NAME&lt;a class=&quot;zola-anchor&quot; href=&quot;#name&quot; aria-label=&quot;Anchor link for: name&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;browser-history - external history of web browsers, such as netscape&lt;/p&gt;
&lt;h3 id=&quot;synopsis&quot;&gt;SYNOPSIS&lt;a class=&quot;zola-anchor&quot; href=&quot;#synopsis&quot; aria-label=&quot;Anchor link for: synopsis&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;browser-history&lt;/strong&gt; [ &lt;strong&gt;options&lt;/strong&gt; ]&lt;/p&gt;
&lt;h3 id=&quot;description&quot;&gt;DESCRIPTION&lt;a class=&quot;zola-anchor&quot; href=&quot;#description&quot; aria-label=&quot;Anchor link for: description&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Browser-History&lt;/em&gt; is a client-side X daemon maintaining a
browser-independent global history of all the web sites you visited .Its
usage is very simple, just put the following line in your .xinitrc or
your X start-up script:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;browser-history &amp;amp;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And open the file &lt;strong&gt;~/.browser-history/history-log.html&lt;/strong&gt; and bookmark
it.&lt;/p&gt;
&lt;p&gt;Browser-history came from the will to overcome a Netscape bug: there was
no global history, and if you close a window, its whole history is lost.
For people browsing lots of sites, having a possibility to track back
where one has been before means that you dont have to put everything in
your bookmarks file. If you are not sure if a site may be worth
remebering, don&#39;t add it in your bookmarks. If you need it later, just
browse your history files.&lt;/p&gt;
&lt;p&gt;Later, it came to our minds that this also could be a valuable add-on to
people writing experimental browsers, so they dont have to add this
functionality to their browser itself.&lt;/p&gt;
&lt;p&gt;Browser-history is a small and efficient daemon. Real user services
could be built on top of the log files it maintains for more
possibilities (graphical representation, advanced search options,
collective histories). It can be seen as a quick-and-dirty hack wrt to
the general solution of using a personal proxy to provide this history
and housekeeping facilities. But in the meantime, it is easy to use and
it works.&lt;/p&gt;
&lt;h3 id=&quot;implementation&quot;&gt;IMPLEMENTATION&lt;a class=&quot;zola-anchor&quot; href=&quot;#implementation&quot; aria-label=&quot;Anchor link for: implementation&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Browser-History&lt;/em&gt; spies your web browser and logs
in &lt;code&gt;~/.browser-history/history-log.html&lt;/code&gt; all the URLs you went through. You
can then browse the log under Netscape or other browsers via the URL:
&lt;strong&gt;file:~/.browser-history/history-log.html&lt;/strong&gt; (replace the ~ by your home
directory). It tracks automagically all already present browser windows,
and all new ones created in the future. This program has no user
interface. It just appens information to a log file in html format so
you can browse it through a web browser. If more that one hour has
passed since last entry, it draws an horizontal lines, and adds H1
headers to delimit new days. Each week (sunday mornings), it archives
the week history, compresses it by gzip (that you must have in your
path), and starts a new history with links to the older ones. To make
room you can just remove the obsolete history files. You can search
files for string XXX in shell via:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;zgrep XXX ~/.browser-history/*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This version (2.6) works with Netscape, Arena and Amaya.&lt;/p&gt;
&lt;p&gt;URLs can be excluded from logging by putting them, one per line in the
file &lt;strong&gt;~/.browser-history/history-log.exclude&lt;/strong&gt; , then, if an URL begins
with a line from this file, it is not logged. In this file, empty lines
or lines beginning by # are comments This file is read once at startup,
and re-read when receiving the signal 1. e.g:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;# We exclude local files file: # Exclude search engines...
http://home.netscape.com http://guide.infoseek.com&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When browser-history is run, it looks if another one is running, and by
default it kills the previous one if it is an older version. Otherwise,
it the new one is the same version number or older, it just aborts.&lt;/p&gt;
&lt;h3 id=&quot;options&quot;&gt;OPTIONS&lt;a class=&quot;zola-anchor&quot; href=&quot;#options&quot; aria-label=&quot;Anchor link for: options&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;All options can be given by their first letter: you can specify either
-verbose or -v, but you cannot group options, e.g. you must say &lt;strong&gt;-v
-k&lt;/strong&gt; , but not &lt;strong&gt;-vk&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-display&lt;/strong&gt; &lt;em&gt;display_name&lt;/em&gt;&lt;br /&gt;
Specifies X display, otherwise contents of $DISPLAY is used&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-verbose&lt;/strong&gt;&lt;br /&gt;
outputs information on what it is doing. useful for debug.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-Version&lt;/strong&gt;&lt;br /&gt;
prints version number and exit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-logdir&lt;/strong&gt; &lt;em&gt;directory&lt;/em&gt;&lt;br /&gt;
which directory to store files into? defaults to ~/.browser-history&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-gzip&lt;/strong&gt; &lt;em&gt;gzip_filename&lt;/em&gt;&lt;br /&gt;
the complete path to the &lt;strong&gt;gzip&lt;/strong&gt; compressor. Defaults to &quot;gzip&quot;. E.g:&lt;/p&gt;
&lt;p&gt;-gzip /usr/gnu/bin/gzip&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-seconds&lt;/strong&gt; &lt;em&gt;delay&lt;/em&gt;&lt;br /&gt;
if two entries are made are more than &lt;em&gt;delay&lt;/em&gt; seconds apart, an
horizontal rule will separate them, else just a simple line break.
Defaults to one hour (3600).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-replace&lt;/strong&gt;&lt;br /&gt;
If there is an already running browser-history on the display, aborts.
Default is to replace it only if the version is older than ours.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-noreplace&lt;/strong&gt;&lt;br /&gt;
If there is an already running browser-history on the display, aborts.
Default is to replace it only if the version is older than ours.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-kill&lt;/strong&gt;&lt;br /&gt;
If there is an already running browser-history on the display, kills it,
then terminates immediately in all cases..TP &lt;strong&gt;-DontGrab&lt;/strong&gt; Never Grab
the X Server, which might cause deadlocks while debugging, when
browser-history or gdb tries to print on the grabbed xterm or emacs.&lt;/p&gt;
&lt;h3 id=&quot;log-file-format&quot;&gt;LOG FILE FORMAT&lt;a class=&quot;zola-anchor&quot; href=&quot;#log-file-format&quot; aria-label=&quot;Anchor link for: log-file-format&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A log file can have some decorative HTML to represent days, but each
entry has the form: (on a single line since version 2.4)&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #4C4F69; background-color: #EFF1F5;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;separator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;b&amp;gt;name&amp;lt;/b&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;a href=&amp;quot;URL&amp;quot;&amp;gt;URL&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    YYYY/MM/DD-HH:MN:SS &amp;lt;small&amp;gt;windowid&amp;lt;/small&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;where the following items are:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;separator: either &lt;hr&gt; or &lt;br&gt;
name: the name of the document (window title)
URL: its URL
YYYY/MM/DD-HH:MN:SS: year, month number, day number, hour,
minutes, seconds. (2-digit numbers)
windowid: the X window ID of the browser window, in hexadecimal&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; Before version 2.4, the 4 sub-parts were separated by newlines,
but since 2.4, they are only blank-separated to ease searching for URL
in log files via &quot;grep&quot;. &lt;strong&gt;Note&lt;/strong&gt; Before version 2.5, the year was
stored in 2 digits. Now it is stored in 4 (or more :-) digits, to fix
this Y2K bug&lt;/p&gt;
&lt;h3 id=&quot;home&quot;&gt;HOME&lt;a class=&quot;zola-anchor&quot; href=&quot;#home&quot; aria-label=&quot;Anchor link for: home&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The latest version of &lt;strong&gt;browser-history&lt;/strong&gt; can be found at:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ftp://koala.inria.fr/pub/browser-history&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and its WWW home page, with full technical documentation is at:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;http://koala.ilog.fr/colas/browser-history&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;author&quot;&gt;AUTHOR&lt;a class=&quot;zola-anchor&quot; href=&quot;#author&quot; aria-label=&quot;Anchor link for: author&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Colas Nahaboo, &lt;strong&gt;http://koala.ilog.fr/colas&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;copyright&quot;&gt;COPYRIGHT&lt;a class=&quot;zola-anchor&quot; href=&quot;#copyright&quot; aria-label=&quot;Anchor link for: copyright&quot;&gt;🔗&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;browser-history&lt;/em&gt; bears the same license as the X Window System: you can
do everything with this code (selling it, modifying it), except suing me
or using my name in your advertisements, or expecting any kind of
support or guarantee.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Colas Nahaboo X mouse wheel scroll page</title>
        <published>1997-12-30T00:00:00+00:00</published>
        <updated>2026-04-25T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/blog/colas-nahaboo-x-mouse-wheel-scroll-page/"/>
        <id>https://colas.nahaboo.net/blog/colas-nahaboo-x-mouse-wheel-scroll-page/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/blog/colas-nahaboo-x-mouse-wheel-scroll-page/">&lt;div class=&quot;obsolete-overlay&quot;&gt;
    Legacy
&lt;/div&gt;
&lt;style&gt;
.obsolete-overlay {
    position: fixed;
    top: 40px;
    left: 60%;
    transform: translate(-50%, -50%) rotate(-5deg);
    font-size: 2vw;
    font-weight: 800;
    color: rgba(255, 0, 0, 0.4);
    background: rgba(255, 255, 0, 0.2);
    border: 15px solid rgba(255, 0, 0, 0.3);
    padding: 10px 20px;
    z-index: 9999;
    pointer-events: none;
    text-transform: uppercase;
    white-space: nowrap;
    user-select: none;
}
&lt;/style&gt;
&lt;p&gt;On December 30, 1997, I started this page to help developers manage the — then new — mouse wheel. My goal was to encourage a standard scrolling direction for the X Window System on Unix and Linux.&lt;/p&gt;
&lt;p&gt;It quickly became the most-viewed page on my personal site, and even across all INRIA-hosted websites at the time. However, as mouse wheels became mainstream, the page lost its relevance. I let it quietly disappear in 2018 when I upgraded my site.&lt;/p&gt;
&lt;p&gt;Seeing that this remains one of my most accessed URLs even in 2026, I decided to create this legacy page at the same legacy URL. It allows people to easily find the historical version on the Web Archive, specifically the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https://web.archive.org/web/20150906210929/https://colas.nahaboo.net/mouse-wheel-scroll/&quot;&gt;latest version of 2015-09-06&lt;/a&gt;, from which is the screenshot:&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;a href=&#39;https://web.archive.org/web/20150906210929/https://colas.nahaboo.net/mouse-wheel-scroll/&#39; title=&#39;web archive version&#39;&gt;&lt;img src=&#39;CNXMWSP-Screenshot.png&#39;&gt;&lt;/a&gt;&lt;/p&gt;
</content>
        
    </entry>
</feed>
