<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="/rss.xsl" media="all"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Roastidio.us User Picks KjQKkQVg</title>
<link>https://roastidio.us/user/KjQKkQVg</link>
<atom:link href="https://roastidio.us/feed/KjQKkQVg" rel="self" type="application/rss+xml"></atom:link>
<description>Roastidio.us User Picks KjQKkQVg</description>
<item>
<title>A Critique of GPUI</title>
<link>https://blog.zortax.de/posts/a-critique-of-gpui</link>
<guid isPermaLink="false">uZO8wjjlcpMigMm8lourhqQJBDBBq-bXft4Jvg==</guid>
<pubDate>Mon, 09 Nov 2026 18:08:58 +0000</pubDate>
<description>Personal Notes</description>
<content:encoded>&lt;p&gt;Recently, there has been a trend of more desktop GUI apps being built using
native rust GUI frameworks. And there are now even well known electron apps
getting official rewrites: Discord announced their app is being rewritten using
GPUI.&lt;sup&gt;1&lt;/sup&gt; Meanwhile, a lot of the LLM-clones being published seem to choose
egui. In this post, I want to explain why I am not sure those frameworks are a
good foundation to build on.&lt;/p&gt;&lt;p&gt;To put it plainly: I believe both GPUI’s and egui’s state models are dead
ends for complex desktop applications. Both are impressive projects, and they
have their place. Zed genuinely feels fast and nice to use, and I use egui
myself for debug interfaces in bevy games. But I don’t think those frameworks
should be the default choice for native desktop apps.&lt;/p&gt;&lt;p&gt;I want to make two arguments:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Every UI architecture ends up needing to know what changed and who depends on
it, or performance characteristics will not scale. A framework whose state
model cannot say so makes the application say it by hand, at the cost of
whatever made that framework’s API semantics attractive in the first place.&lt;/li&gt;
&lt;li&gt;Once you admit you want that precision, components that run once, with
signals and reactive holes, are the simplest API for it.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;em&gt;Disclosure: I ported GPUI’s current Linux renderer to wgpu&lt;sup&gt;2&lt;/sup&gt;, I built the
benchmark harness used below, and I work on
&lt;a href=&quot;https://github.com/zortax/zgui&quot;&gt;zgui&lt;/a&gt;, a signal-based Rust framework that
appears in the charts.&lt;/em&gt;&lt;/p&gt;&lt;h2&gt;The only question that matters&lt;/h2&gt;&lt;p&gt;Raph Levien quotes Ron Minsky: “hidden inside of every UI framework is some
kind of incrementalization framework.”&lt;sup&gt;3&lt;/sup&gt; A UI is a function of state, and
state changes a little at a time. But if that function becomes expensive, you
might want to start looking for ways to derive a faster way to update pixels on
the screen from an incremental state change. So every framework has to answer
one question: when one value changes, what runs?&lt;/p&gt;&lt;div&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Model&lt;/th&gt;&lt;th&gt;What a write runs&lt;/th&gt;&lt;th&gt;Who finds the change&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Immediate (egui)&lt;/td&gt;&lt;td&gt;All UI code, next frame&lt;/td&gt;&lt;td&gt;Nobody&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Elm (Iced)&lt;/td&gt;&lt;td&gt;All of &lt;code&gt;view&lt;/code&gt;, then a diff&lt;/td&gt;&lt;td&gt;The diff&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Views (GPUI)&lt;/td&gt;&lt;td&gt;Every view without a cache&lt;/td&gt;&lt;td&gt;You, with &lt;code&gt;notify&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Signals, re-run (Freya, Compose)&lt;/td&gt;&lt;td&gt;Components that read it&lt;/td&gt;&lt;td&gt;The framework&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Signals, run once (Floem, Solid, zgui)&lt;/td&gt;&lt;td&gt;Closures that read it&lt;/td&gt;&lt;td&gt;The framework&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;I understand why people like the first three. No state to synchronize, one
place where state lives, a &lt;code&gt;render&lt;/code&gt; function that is plain Rust, no macros or
separate compiler. I’m gonna make the argument that these approaches don’t
scale, and fixing the underlying problem defeats what makes these models
simple and easy to reason about.&lt;/p&gt;&lt;h2&gt;GPUI: &lt;code&gt;notify&lt;/code&gt; is zone.js&lt;/h2&gt;&lt;p&gt;GPUI calls itself “a hybrid immediate and retained mode” framework.&lt;sup&gt;4&lt;/sup&gt; It
retains state in entities. The UI is defined in &lt;code&gt;render&lt;/code&gt; functions, changing
state must trigger a rerun.&lt;/p&gt;&lt;p&gt;It is ordinary Rust. You can use &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt; and local variables, and there
aren’t any weird wrappers. State changes require an explicit notification:&lt;/p&gt;&lt;p&gt;&lt;code&gt;notify&lt;/code&gt; carries the entity id.&lt;sup&gt;5&lt;/sup&gt; Since Rust doesn’t have a write barrier on
&lt;code&gt;&amp;amp;mut&lt;/code&gt;, GPUI cannot see which field changed (or whether anything changed at
all). The Angular team wrote this about zone.js in 2023: it “is only capable of
notifying us when something &lt;em&gt;might&lt;/em&gt; have happened”, and “This approach has not
scaled well.”&lt;sup&gt;6&lt;/sup&gt; &lt;code&gt;notify&lt;/code&gt; is more precise than a zone, since it names an
entity, but ultimately it makes the same kind of statement. Below that id, GPUI
knows nothing, so it re-renders every view that is not behind a valid
&lt;code&gt;.cached()&lt;/code&gt; boundary. And in practice, GPUI often rerender every view, because
&lt;code&gt;.cached()&lt;/code&gt; is rarely used by application authors, and imposes certain
restrictions on layout semantics.&lt;/p&gt;&lt;p&gt;GPUI has a reputation of being “fast”. And while constants might be relatively
low, asymptotically, it is leaving a lot on the table. So I ran a few benchmarks,
that specifically test how much a sparse state change in a large UI actually costs.&lt;/p&gt;&lt;p&gt;At 3,000 live rows with a cached view per row, changing one label takes 8.4 ms.
A hover, a keystroke and writing a value equal to the old one all cost about
the same, because the cost follows the tree and not the change. It grows by
about 3 ms per 1,000 live rows. Write the rows as plain elements, as in the
code above, and the same label takes 92 ms. A hand-written equality guard takes
the equal write from 7.9 ms to 0.9 µs (demonstrating how much is left for each
call site to find).&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/scaling-linear.png&quot; alt=&quot;On a linear axis, the cost per row is the slope&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/scaling-linear-dark.png&quot; alt=&quot;On a linear axis, the cost per row is the slope&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;This doesn’t mean that every GPUI app is slow, but it shows the limit of the
state model. Especially with more expensive layout, you &lt;em&gt;do hit&lt;/em&gt; this wall
in practice. Zed might feel fast, but the truth is that Zed is a relatively
simple app, UI wise. The app’s chrome contains a few buttons, in a simple
layout, a sidebar and a text editor, and the text editor is implemented as a
custom element, completely bypassing GPUI’s layout and view semantics. By their
own account, a window “has tens of nodes and a few thousand elements”.&lt;sup&gt;7&lt;/sup&gt;&lt;/p&gt;&lt;h2&gt;Making GPUI precise defeats GPUI&lt;/h2&gt;&lt;p&gt;The obvious fix is to retain more. Zed has experimental branches for this, and
Longbridge’s gpui-fast is a fork that keeps every view’s subtree between
frames.&lt;sup&gt;8&lt;/sup&gt; &lt;sup&gt;9&lt;/sup&gt; It works, within a limit: the smallest thing either one can
reuse is a view. So to update one label without rebuilding the sidebar, the
label has to be a view:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;pub struct UnreadBadge { unread: usize, _watch: Subscription }

impl UnreadBadge {
    pub fn new(inbox: Entity&amp;lt;Inbox&amp;gt;, cx: &amp;amp;mut Context&amp;lt;Self&amp;gt;) -&amp;gt; Self {
        let unread = inbox.read(cx).unread();
        let _watch = cx.observe(&amp;amp;inbox, |this, inbox, cx| {
            let unread = inbox.read(cx).unread();
            if unread != this.unread {
                this.unread = unread;
                cx.notify();
            }
        });
        Self { unread, _watch }
    }
}

impl Render for UnreadBadge {
    fn render(
        &amp;amp;mut self,
        _: &amp;amp;mut Window,
        _: &amp;amp;mut Context&amp;lt;Self&amp;gt;,
    ) -&amp;gt; impl IntoElement {
        format!(&amp;quot;{} unread&amp;quot;, self.unread)
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Its owner then has to create it and keep the handle:&lt;/p&gt;&lt;p&gt;That is an entity, a &lt;code&gt;Render&lt;/code&gt; impl, a subscription, a stored copy of the value,
a hand-written guard and an owner, all to express that one label depends on one
count. In a signal framework it is this:&lt;/p&gt;&lt;p&gt;The rest of GPUI’s API works against this too. &lt;code&gt;Render&lt;/code&gt; takes no props, so
parents push values into child entities during their own render. &lt;code&gt;RenderOnce&lt;/code&gt;
components, which is what buttons and rows are, draw inside their parent’s view
and are no boundary at all. List rows are closures, so a row view means
managing a keyed map of entities by hand.&lt;/p&gt;&lt;p&gt;And it only helps where state happens to line up with views. I reran gpui-fast’s
own 60-panel benchmark, drew each frame once, and then moved the state:&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/retention.png&quot; alt=&quot;Retention pays only where state already matches the views&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/retention-dark.png&quot; alt=&quot;Retention pays only where state already matches the views&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;With state owned by each panel, one change saves 83%. With a shared model,
retention makes the same frame 11% slower. The window and the edit are
identical. In real Zed, the Zed team measured retention “1–3% slower than off
on ordinary workloads”, found that “Most of the real-Zed win” came from other
work, and warned that “microbenchmark wins didn’t predict real-Zed
results”.&lt;sup&gt;8&lt;/sup&gt; gpui-fast is real progress and costs little to adopt: it takes
the 3,000-row label from 8.4 to 3.4 ms. But that frame renders three views and
lays out one element, and still spends 3.4 ms, because the frame is still a
walk over the whole tree.&lt;/p&gt;&lt;p&gt;The web has already walked this road. Redux’s style guide says “Prefer having
more UI components subscribed to the Redux store and reading data at a more
granular level”.&lt;sup&gt;10&lt;/sup&gt; MobX says to “create lots of small observer
components”.&lt;sup&gt;11&lt;/sup&gt; Both tell you to make a boundary per projection, manually,
because the framework can’t infer it.&lt;/p&gt;&lt;p&gt;This is the part I find hardest to get past. People choose GPUI because &lt;code&gt;render&lt;/code&gt;
is a plain function of state. A UI where each projection is a separately owned
entity with a subscription and a guard is no longer that. It is a signal graph
built by hand from much heavier parts, where a missed edge is silent. Zed’s own
design note says “Missing notifications are application bugs”.&lt;sup&gt;12&lt;/sup&gt; Keep the
pleasant API and you get view-sized updates. Take the precision and you lose the
pleasant API. A signals crate on top would not change the trade, because its
smallest sink is still a view. Reaching one node with no &lt;code&gt;render&lt;/code&gt; running needs
writes the framework can see and nodes that outlive a frame, and that means a
new state model and a new element contract.&lt;/p&gt;&lt;h2&gt;Elm: deceptively simple at small scales&lt;/h2&gt;&lt;p&gt;At the size it is usually shown, the Elm architecture is a deceptively simple
UI model: one state value, one &lt;code&gt;update&lt;/code&gt;, one &lt;code&gt;view&lt;/code&gt;, and every change has a
name. While large applications do use it successully,&lt;sup&gt;13&lt;/sup&gt; &lt;sup&gt;14&lt;/sup&gt; I do want to
make the point that this clarity belongs to the small case, and in a complex
application signals and stores are arguably easier to reason about.&lt;/p&gt;&lt;p&gt;Take the same &lt;code&gt;unread&lt;/code&gt; count. It has to be right after every message, so either
&lt;code&gt;view&lt;/code&gt; recomputes it on every update or &lt;code&gt;update&lt;/code&gt; maintains it:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;match message {
    InboxMessage::MarkRead(i) =&amp;gt; {
        if self.threads[i].unread {
            self.threads[i].unread = false;
            self.unread -= 1;
        }
    }
    InboxMessage::Delete(i) =&amp;gt; {
        if self.threads.remove(i).unread {
            self.unread -= 1;
        }
    }
    InboxMessage::Arrived(thread) =&amp;gt; {
        self.unread += thread.unread as usize;
        self.threads.push(thread);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The definition of &lt;code&gt;unread&lt;/code&gt; is now nowhere in particular. It is spread across
every arm that touches a thread, and each new message has to remember it. The
compiler checks that the &lt;code&gt;match&lt;/code&gt; is exhaustive, but it does not check the
arithmetic. The memo above has one definition, and a new writer cannot forget
it.&lt;/p&gt;&lt;p&gt;The same thing happens with location. Where does a hover state or a half-typed
draft live? Single source of truth says in the model, with a message type
routed down and an outcome routed back up. Elm’s guide: “Actively trying to
make components is a recipe for disaster in Elm.”&lt;sup&gt;15&lt;/sup&gt;. Iced recommends
returning an &lt;code&gt;Action&lt;/code&gt; to the parent.&lt;sup&gt;16&lt;/sup&gt; Iced’s maintainer says components in
this architecture always end “with pain”, and also makes the best case for the
discipline: avoiding them “forces you to think hard about your data
model”.&lt;sup&gt;17&lt;/sup&gt; Okay, I guess that’s a fair argument. But cosmic-files has 136
top-level message variants and 73 more for a tab, plus a &lt;code&gt;Tab::update&lt;/code&gt; that
returns commands for the parent to interpret.&lt;sup&gt;18&lt;/sup&gt; Everything in that is
explicit, and none of it is simple.&lt;/p&gt;&lt;p&gt;The architecture also has the same issue GPUI has. The &lt;code&gt;update&lt;/code&gt; implementation
tells you what a message writes, it cannot tell you what read the field.
Anything inside the &lt;code&gt;view&lt;/code&gt; might. Elm’s architecture doesn’t answer “what
changed?”, it answers “what happened?”. Session export might be useful in some
scenarios, but it is not useful for scalable performance characteristics.&lt;sup&gt;19&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;This is what I read in the web’s history. Redux is the best-known relative of
this design, and its docs read like a field report. Treat a portion of your
store “as if it were a database”.&lt;sup&gt;20&lt;/sup&gt; Selectors “will be re-run after every
dispatched action”.&lt;sup&gt;21&lt;/sup&gt; The core package is “obsolete”, replaced by a toolkit
made to remove boilerplate.&lt;sup&gt;22&lt;/sup&gt; Outside React, the mainstream has moved to
tracked reads. Angular, Vue, Svelte and Solid build on signals or something
equivalent, Preact offers them, and Svelte’s team put it this way: “we’ve come
to the realisation that Knockout was right all along.”&lt;sup&gt;23&lt;/sup&gt; Inside React, Jotai
and MobX bring tracking in as libraries, and Legend-State even offers a “render
once” style.&lt;sup&gt;24&lt;/sup&gt; Most applications are still on React, and React’s team
disagrees, which I come back to below. So the convergence is on the state model,
outside one large exception.&lt;/p&gt;&lt;p&gt;Performance follows the same line. Since Iced rebuilds all of &lt;code&gt;view&lt;/code&gt; after
every batch of messages, one label at 3,000 rows builds 39,023 widgets and
takes 7.3 ms. &lt;code&gt;Lazy&lt;/code&gt; on every row only gets that to 5.7 ms, because &lt;code&gt;view&lt;/code&gt;
still has to visit each row to hash its key. The official &lt;code&gt;lazy&lt;/code&gt; example keys
on a &lt;code&gt;version: u8&lt;/code&gt; that four &lt;code&gt;update&lt;/code&gt; arms bump by hand.&lt;sup&gt;25&lt;/sup&gt; That is a dirty
flag with a nicer name. In fairness, cosmic-files and Halloy use no &lt;code&gt;lazy&lt;/code&gt; at
all, and on a virtualized list Iced is one of the fastest frameworks I
measured, at 0.19 ms. A bounded screen rebuilds cheaply. But asymptotic
complexity is clear. And similar to GPUI, the API semantics simply can’t
express the necessary information.&lt;/p&gt;&lt;p&gt;There is actually precedence for this: Vizia shows what happens when you add
precision to this model. It moved from lenses to signals in March 2026 and kept
its &lt;code&gt;Model&lt;/code&gt; and event dispatch.&lt;sup&gt;26&lt;/sup&gt; This is its counter, shortened:&lt;sup&gt;27&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;The label reads the signal directly, and the same closure that builds the
button created it. The enum, the dispatch and the handler exist to carry one
call to &lt;code&gt;update&lt;/code&gt;. Vizia was never strict Elm, since its views are built once,
and signals were a sensible move: it got per-field writes. But look at what
remains of Elm’s reasons. State is a graph of mutable cells, &lt;code&gt;Model&lt;/code&gt; is a bag
of handles, and &lt;code&gt;event&lt;/code&gt; is a &lt;code&gt;&amp;amp;mut self&lt;/code&gt; side effect. You now have two systems
for saying that something changed. So my objection to adding signals to the Elm
architecture really is the same as with GPUI: they work, and they remove what
you came for.&lt;/p&gt;&lt;h2&gt;A quick note on immediate mode&lt;/h2&gt;&lt;p&gt;egui’s pitch is the best in the field: “You don’t have to worry about app state
and GUI state being out-of-sync”.&lt;sup&gt;28&lt;/sup&gt; For a tool, this is hard to beat:&lt;/p&gt;&lt;p&gt;The price is that a frame costs the size of the UI, independent of what
changed. At 3,000 rows every small edit takes about 32 ms, or about 19 ms with
accessibility off. egui’s author is candid about the trade: immediate mode is
“easier to use, but less powerful”.&lt;sup&gt;28&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;As the application grows, the original attraction goes. The layout paradox is “a
fundamental shortcoming”.&lt;sup&gt;28&lt;/sup&gt; Long lists need &lt;code&gt;show_rows&lt;/code&gt;, which takes one
fixed row height. Rerun, the largest egui application I know of, clamps queries
by “inspecting egui state from the previous frame”.&lt;sup&gt;29&lt;/sup&gt; Anything expensive goes
behind a cache keyed on your data. A cache that has to agree with your data is
the synchronization problem immediate mode set out to remove, now in application
code, one frame late.&lt;/p&gt;&lt;h2&gt;One engine, different wiring&lt;/h2&gt;&lt;p&gt;The harness can show this directly, because some frameworks can be wired
coarsely and finely on the same engine:&lt;/p&gt;&lt;p&gt;I benchmarked some of the engines in two ways, once in the most fine grained
way they can be used, and once in a coarser way. The results show how much there
is to gain with fine-grained reactivity.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/granularity.png&quot; alt=&quot;Tracking pays, unless the view function still has to run&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/granularity-dark.png&quot; alt=&quot;Tracking pays, unless the view function still has to run&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Two things stand out. Iced’s factor is small because the view function still
runs. And Floem’s coarse case is worth a look: every cell reads one global
revision signal, which is &lt;code&gt;notify&lt;/code&gt; in signal clothing. It is the slowest result
on the chart. So signals do not rescue coarse state. The React team found the
same thing from the other side: on a benchmark with “one giant input”, a
signals-style runtime disappointed, and Joe Savona concluded the data model “is
just as important, maybe more so” than the algorithm.&lt;sup&gt;30&lt;/sup&gt; The state has to be
shaped like the reads. That is why I call this a state model problem. A good
API should make it easy to align the data model with its UI projection.&lt;/p&gt;&lt;h2&gt;Why run once&lt;/h2&gt;&lt;p&gt;Suppose you accept all of that. You want the framework to track reads, and you
want state shaped to match. What is the simplest API?&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;pub fn sidebar(threads: RwSignal&amp;lt;Vec&amp;lt;Thread&amp;gt;&amp;gt;) -&amp;gt; impl IntoView {
    // Runs once, when the sidebar mounts.
    let unread = Memo::new(move |_| {
        threads.with(|ts| ts.iter().filter(|t| t.unread.get()).count())
    });

    Stack::vertical((
        Label::derived(move || format!(&amp;quot;{} unread&amp;quot;, unread.get())),
        dyn_stack(move || threads.get(), |t| t.id, thread_row),
    ))
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That is the whole thing. The body runs once. The closures you hand to the
framework run again when something they read changes. A local variable is a
local variable. There are no hook rules, no dependency arrays, no stale
closures and no &lt;code&gt;PartialEq&lt;/code&gt; on props. Nothing reconstructs a row’s identity,
because the row is still there.&lt;/p&gt;&lt;p&gt;Compare signals with re-running components, which is Freya’s model. It works
well: one keystroke at 3,000 rows costs 1.2 ms. But look at a counter:&lt;sup&gt;31&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;use_state&lt;/code&gt; exists because that line runs again. You now hold both models: read
tracking decides which scope re-runs, and then re-render semantics apply inside
it, with hooks, prop equality and a diff. Finer updates need smaller components,
which is GPUI’s problem at a much lower price. What the re-running body buys is
ordinary control flow, and that is the serious objection.&lt;/p&gt;&lt;p&gt;Dan Abramov makes a compelling argument.&lt;sup&gt;32&lt;/sup&gt; Run-once puts your rendering
logic in closures, so top-level control flow stops working, and you group code
around values and not around logic. “The beauty of React is that making things
‘computed’ is an optimization, not a requirement.” He is right about it. This
compiles, but the first line never updates:&lt;/p&gt;&lt;p&gt;A reactive &lt;code&gt;if&lt;/code&gt; has to become a &lt;code&gt;dyn_container&lt;/code&gt;, and a &lt;code&gt;for&lt;/code&gt; a &lt;code&gt;dyn_stack&lt;/code&gt;.
Solid 2.0 had to add dev warnings for top-level reads.&lt;sup&gt;33&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;But the same comment contains the reason I land the other way. He says Solid’s
regrouping is “Similar to how you have to restructure your code around the
values when you optimize it with useMemo.” Exactly. If your application never
needs that, React’s model may be simpler. If it does, you pay for the
regrouping either way, and the only choice is when: from the start, or later
under a profiler. Ryan Carniato’s reply is the one I agree with: “In Solid you
always write as if the data is derived so you don’t refactor to optimize.”&lt;sup&gt;32&lt;/sup&gt;
Once you know you want this precision, run-once is the API that stops
pretending otherwise. The failure modes also favour it. A forgotten hole goes
stale on the first update, in the place you wrote it. A forgotten &lt;code&gt;notify&lt;/code&gt;
depends on what else happened to redraw.&lt;/p&gt;&lt;p&gt;To be perfectly honest, the ecosystem’s wider convergence is on read tracking
in general, and not on run-once specifically. Angular considered per-binding
updates and chose per-view, in writing, and it lands within about 1 ms of Solid
on a partial update.&lt;sup&gt;6&lt;/sup&gt; &lt;sup&gt;34&lt;/sup&gt; Apple and Google, who control their languages,
kept re-running bodies with &lt;code&gt;@Observable&lt;/code&gt; and Compose.&lt;sup&gt;35&lt;/sup&gt; &lt;sup&gt;36&lt;/sup&gt; A hole is
itself a re-run scope, so what differs is how big the default scope is. Two things
I want to note on this though:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;First, those systems pay for their larger scopes with a compiler. Compose has
a compiler plugin, Angular compiles templates, and React’s compiler is the
serious rival to everything here: it keeps React’s API and removes many
needless re-renders, with loads up to 12% better.&lt;sup&gt;37&lt;/sup&gt; For Rust, I suspect that
most people that prefer immediate mode or elm (or whatever GPUI is) would not
like the idea of an additional compiler. A proc macro only sees tokens, not
types, and &lt;code&gt;render&lt;/code&gt; is an arbitrary function, so there is no pass that can
split it into scopes. What Rust can express cheaply is a closure.&lt;/li&gt;
&lt;li&gt;Second, their own guidance keeps describing the same problem: “Defer reads as
long as possible” for Compose, and “Unnecessary view body updates can really
add up” for SwiftUI.&lt;sup&gt;38&lt;/sup&gt; &lt;sup&gt;39&lt;/sup&gt; A framework that runs the body once removes
that category at component level.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;View-level rerun and fine-grained signals can have the same performance
ceiling. But signals encourage fine-grained state projections and memoization
from the beginning, for view-level rerun its an explicit choice that often
leads to more boilerplate.&lt;/p&gt;&lt;h2&gt;Signals do not automatically make your app fast&lt;/h2&gt;&lt;p&gt;Fine-grained reactivity does not make an app fast on its own.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/models.png&quot; alt=&quot;Signals alone do not flatten the curve&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/models-dark.png&quot; alt=&quot;Signals alone do not flatten the curve&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;Floem’s reactivity does exactly what it promises. Changing a label runs 5
effects and spends 0.01 ms in reactive work, then about 14 ms in layout, because
Taffy does not know that one leaf moved. (Floem also has a known bug where that
edit never repaints, so treat this as a floor.) Vizia runs 4 bindings, then
walks all 120,091 entities, for 46 ms. Slint writes an equal value in 4 µs, and
takes 172 ms for a label, in a pass that walks about 30,000 items. Freya
produces 5 mutations, then visits 57,050 layout nodes to recompute 14. GPUI
beats most of them on this edit.&lt;/p&gt;&lt;p&gt;This is the distinction the argument depends on. All of those linear costs are
in the engine respectively. Nothing in the application’s code requires them, so
they can be fixed behind the same API without changing an application. zgui
shows how far that goes: 0.69 ms for the label at 3,000 rows and about 0.26 ms
per 1,000 rows, around 12 times flatter than GPUI. It is still not flat, and it
is my framework and was tuned on this harness, so take these numbers with a
grain of salt. In Iced and egui the linear cost is in the contract: the API
says your code runs. No engine work can remove that, and app code has to
change. GPUI probably sits somewhere in between, which is why gpui-fast can
improve the situation to some extent.&lt;/p&gt;&lt;p&gt;At this point, I wan’t to share a more detailed benchmark matrix. Read the
re-running columns down the first five rows and they barely move, because they
do not depend on the edit. The signal columns move a lot, because the
underlying implementations differ.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/comparison.png&quot; alt=&quot;Re-running makes most edits cost the same. Signals do not&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://blog.zortax.de/images/a-critique-of-gpui/comparison-dark.png&quot; alt=&quot;Re-running makes most edits cost the same. Signals do not&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;p&gt;The bottom of that grid is also where the cost signals have becomes visible.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Creation.&lt;/strong&gt; Filtering at 3,000 live rows takes 56 ms in Iced, 67 in egui
and 123 in GPUI, against 371 in zgui, 835 in Floem and 982 in Freya. On a
virtualized list it is 1.0 ms in Iced and 7.2 in zgui. “Setting up the
dependency graph is not free.”&lt;sup&gt;6&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory.&lt;/strong&gt; Resident memory usage for large scenes is generally higher the
more a framework retains.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Effects.&lt;/strong&gt; Facebook moved away from two-way binding because “cascading
updates” became hard to predict.&lt;sup&gt;40&lt;/sup&gt; That history is true, and Angular’s docs
still say “Effects should be the last API you reach for.”&lt;sup&gt;41&lt;/sup&gt; Modern graphs
are glitch-free. Careless effects are still difficult to reason about and
quickly result in feedback loops or similar stuff.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rust.&lt;/strong&gt; Signals rely on arena handles and &lt;code&gt;move&lt;/code&gt; closures. Levien thinks
such patterns “adapt poorly to Rust”.&lt;sup&gt;3&lt;/sup&gt; I think they adapt well enough, and
GPUI’s entities are arena handles too, but, admittedly, it is not a free lunch.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;GPUI makes a full frame realitively cheap, and that makes it probably &lt;em&gt;good
enough&lt;/em&gt; for many use-cases. It is certainly enough for an editor whose
expensive surface is handled by hand. For a large application it leaves a
choice: keep the API people like and pay per view, or get precision by writing
a signal graph out of entities. Elm and immediate mode have the same problem.
Each is clearest in the small, and each loses the thing it was chosen for as
precision becomes necessary, and, from my personal experience, that happens faster
than people expect.&lt;/p&gt;&lt;p&gt;Tracked reads are where most of the field has ended up, whatever it started
from. If that is where we are going, I think we should start there, and make
the component a function that runs once.&lt;/p&gt;&lt;h2&gt;Method&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Numbers are medians of apply and settle from my unpublished harness, on one
machine: i9-13900K, RTX 3080 Ti, Vulkan, Linux. Windows, compositor and input
are not included. Frameworks’ maintainers have not reviewed the adapters.&lt;/li&gt;
&lt;li&gt;GPUI is at &lt;code&gt;ddc9eda925&lt;/code&gt; and gpui-fast at &lt;code&gt;86a8228229&lt;/code&gt;. zgui is at &lt;code&gt;082337db&lt;/code&gt;.
These were through September and November 2026, as the best of three passes.&lt;/li&gt;
&lt;li&gt;Cells marked † in the grid failed their correctness oracle: Floem’s label and
keystroke edits, as noted above, and Slint’s font size. Every other charted
cell passed.&lt;/li&gt;
&lt;li&gt;The 60-panel results are gpui-fast’s &lt;code&gt;retained_bench&lt;/code&gt; with my additions, in
test mode, so no GPU work is included. Retention off there is still gpui-fast.&lt;/li&gt;
&lt;li&gt;Figures from Zed’s plan are its authors’, from experimental branches.&lt;/li&gt;
&lt;li&gt;Rust examples were type-checked against the vendored frameworks. Vizia’s and
Freya’s come from their own sources, shortened.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;References&lt;/h2&gt;&lt;div&gt;&lt;sup&gt;1&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://x.com/svishnevskiy/status/2118081920194203799&quot;&gt;Stanislav Vishnevskiy (Discord CTO), post on X, 2026-11-04.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;2&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/zed-industries/zed/pull/46758&quot;&gt;zed#46758, gpui: Remove blade, reimplement linux renderer with wgpu, merged 2026-02-13.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;3&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://raphlinus.github.io/rust/gui/2022/05/07/ui-architecture.html&quot;&gt;Raph Levien, Xilem: an architecture for UI in Rust, 2022-05-07.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;4&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/zed-industries/zed/blob/ddc9eda925/crates/gpui/README.md&quot;&gt;GPUI README, commit ddc9eda925.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;5&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/zed-industries/zed/blob/ddc9eda925/crates/gpui/src/app/context.rs#L216&quot;&gt;GPUI source, commit ddc9eda925: crates/gpui/src/app/context.rs:216.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;6&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/angular/angular/discussions/49684&quot;&gt;Angular, Sub-RFC 1: Signals for Angular Reactivity, 2023-04-03.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;7&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/zed-industries/zed/pull/63800&quot;&gt;zed#63800, gpui: Incremental view rendering with a view tree, draft, closed 2026-09-24.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;8&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/zed-industries/zed/blob/312a04c83/crates/gpui/docs/retained_extraction_plan.md&quot;&gt;crates/gpui/docs/retained_extraction_plan.md, Zed branch gpui-retained-plan, commit 312a04c83, 2026-10-30.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;9&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/longbridge/gpui-fast/blob/86a8228229/README.md&quot;&gt;gpui-fast README, Longbridge, commit 86a8228229.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;10&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://redux.js.org/style-guide/&quot;&gt;Redux Style Guide.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;11&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://mobx.js.org/react-optimizations.html&quot;&gt;MobX, Optimizing React component rendering.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;12&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/zed-industries/zed/blob/c15d4b8e4b/crates/gpui/docs/view_tree.md&quot;&gt;crates/gpui/docs/view_tree.md, Zed branch gpui-retained-node-engine, commit c15d4b8e4b.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;13&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://changelog.com/podcast/319&quot;&gt;Richard Feldman on The Changelog #319, 2018-10-17.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;14&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=40157176&quot;&gt;Michael Murphy (System76), Hacker News comment, 2024-04-25.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;15&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://guide.elm-lang.org/webapps/structure&quot;&gt;An Elm guide, Structure, webapps chapter.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;16&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/iced-rs/iced/blob/8b8e6198/src/lib.rs&quot;&gt;Iced source, commit 8b8e6198: src/lib.rs, Scaling Applications.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;17&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/iced-rs/iced/issues/995&quot;&gt;Héctor Ramón, iced#995, 2021-09-13.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;18&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pop-os/cosmic-files/tree/3868a8e&quot;&gt;cosmic-files at 3868a8e: src/app.rs and src/tab.rs. Counts are approximate.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;19&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/elm/elm-lang.org/blob/master/pages/news/the-perfect-bug-report.elm&quot;&gt;Evan Czaplicki, The Perfect Bug Report, 2016-11-14.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;20&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://redux.js.org/usage/structuring-reducers/normalizing-state-shape&quot;&gt;Redux, Normalizing State Shape.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;21&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://redux.js.org/usage/deriving-data-selectors&quot;&gt;Redux, Deriving Data with Selectors.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;22&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://redux.js.org/introduction/why-rtk-is-redux-today&quot;&gt;Redux, Why Redux Toolkit is How To Use Redux Today.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;23&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://svelte.dev/blog/runes&quot;&gt;Svelte team, Introducing runes, 2023-09-20.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;24&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://legendapp.com/open-source/state/v3/react/fine-grained-reactivity/&quot;&gt;Legend-State, Fine-grained reactivity.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;25&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/iced-rs/iced/blob/8b8e6198/examples/lazy/src/main.rs&quot;&gt;Iced source, commit 8b8e6198: examples/lazy/src/main.rs, lines 12, 127-143, 155.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;26&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vizia/vizia/blob/426d2e7b/MIGRATION_LENS_TO_SIGNALS.md&quot;&gt;Vizia, Migration Guide: Lens-Based State to Signals, commit 426d2e7b.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;27&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vizia/vizia/blob/426d2e7b/examples/7GUIs/counter.rs&quot;&gt;Vizia, examples/7GUIs/counter.rs, commit 426d2e7b.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;28&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/emilk/egui/blob/7809b4fd9a/README.md&quot;&gt;egui README, commit 7809b4fd9a.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;29&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rerun-io/rerun/issues/7562&quot;&gt;rerun#7562, 2024-10-02.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;30&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=uAmRtE52mYk&quot;&gt;Joe Savona, Exploring React Performance, React Conf 2025.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;31&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/marc2332/freya/blob/bf825f73/crates/freya/src/_docs/state_management.rs&quot;&gt;Freya, crates/freya/src/_docs/state_management.rs, commit bf825f73.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;32&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://dev.to/this-is-learning/react-vs-signals-10-years-later-3k71&quot;&gt;Dan Abramov and Ryan Carniato, comments on React vs Signals: 10 Years Later, 2023-03-01.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;33&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/solidjs/solid/discussions/2596&quot;&gt;Solid 2.0 beta notes, 2026-03-03.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;34&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/krausest/js-framework-benchmark&quot;&gt;js-framework-benchmark, results of 2026-11-02, partial update. Fixture is a flat list.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;35&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2023/10149/&quot;&gt;Apple, Discover Observation in SwiftUI, WWDC23.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;36&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.android.com/develop/ui/compose/lifecycle&quot;&gt;Android Developers, Lifecycle of composables.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;37&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://react.dev/blog/2025/10/07/react-compiler-1&quot;&gt;React Compiler v1.0, 2025-10-07.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;38&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.android.com/develop/ui/compose/performance/bestpractices&quot;&gt;Android Developers, Compose performance best practices.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;39&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2025/306&quot;&gt;Apple, Optimize SwiftUI performance with Instruments, WWDC25.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;40&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://facebookarchive.github.io/flux/docs/in-depth-overview/&quot;&gt;Facebook, Flux in-depth overview (archived).&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;sup&gt;41&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://angular.dev/guide/signals/effect&quot;&gt;Angular, Effects guide.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</content:encoded>
</item>
<item>
<title>The Web Is More Than Enough, by Paul Ford (Ftrain)</title>
<link>https://ftrain.com/aboard-the-web-is-more-than-enough</link>
<enclosure type="image/jpeg" length="0" url="https://ftrain.com/art/uploads/aboard-newsletter/the-web-is-more-than-enough-header.png"></enclosure>
<guid isPermaLink="false">QfCR4zfmCc4S2KJSFNh_32MhGIfCSDWogOwjwA==</guid>
<pubDate>Sun, 08 Nov 2026 22:54:54 +0000</pubDate>
<description>Web browsers enable incredibly rich app development—and that’s radically easier than it used to be.</description>
<content:encoded>&lt;figure&gt; &lt;img src=&quot;https://ftrain.com/art/uploads/aboard-newsletter/the-web-is-more-than-enough-header.png?w=1200&quot; alt=&quot;Image of an old-school browser window with a screaming yellow rubber chicken in the center. Background a swirling galaxy in shades of purple and red.&quot; title=&quot;&quot;/&gt; &lt;figcaption&gt;You can have it all, my empire of alert().&lt;/figcaption&gt; &lt;/figure&gt;&lt;p&gt;Last week was fun. We launched &lt;a href=&quot;http://tinylittleoffice.com&quot;&gt;tinylittleoffice.com&lt;/a&gt;—you heard it here first!—and it turned out that lots of folks were in the market for an “office suite that stores data in the URL.” &lt;/p&gt;&lt;p&gt;So many people visited that the server went down (well, I maxxed out the CloudFlare free plan), and ultimately, after I put in my credit card, a couple hundred thousand people came by to check it out. &lt;a href=&quot;https://news.ycombinator.com/item?id=50096142&quot;&gt;People on Hacker News insisted&lt;/a&gt; it was a pointless waste of time, and &lt;a href=&quot;https://github.com/aboard-io/tinylittleoffice&quot;&gt;folks on GitHub&lt;/a&gt; started asking for features and fixes, all of which we’re considering, and some of which we’re doing. &lt;em&gt;The Register&lt;/em&gt; &lt;a href=&quot;https://www.theregister.com/software/2026/10/15/tinylittleoffice-where-the-link-is-the-document/5303328?utm_source=dlvr.it&amp;amp;utm_medium=bluesky&quot;&gt;wrote an article about it&lt;/a&gt;, and it also &lt;a href=&quot;https://www.producthunt.com/products/tiny-little-office&quot;&gt;made it, for a little while, to the top ten of Product Hunt&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;So all good; we will continue to support and enhance it, bit by bit, while we also do stable software development work for our customers and clients. But I did want to pause for a second and point out something that surprised me about the process. It’s this:&lt;/p&gt;&lt;blockquote&gt; &lt;p&gt;The web browser is very, very, very powerful software for building applications.&lt;/p&gt; &lt;/blockquote&gt;&lt;p&gt;I know that is obvious and is the sort of thing I could have said any time in the last 20 years. But now there’s an addendum to the statement: &lt;/p&gt;&lt;blockquote&gt; &lt;p&gt;The web browser is very, very, very powerful software for applications, &lt;em&gt;and the cost of accessing that power is going down seemingly every day.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;&lt;p&gt;I put maybe twice as much effort into building a web-based office suite as I might normally put into writing a long newsletter post. I’m not telling you this because I am a very special boy. I’m telling you because if you want to, you can learn to do it, too.&lt;/p&gt;&lt;p&gt;Fast, cheap, good, right? But even after I had to put in my credit card, CloudFlare hosting costs…$0. Partly because I optimize for cheapness, but partly because that’s just how it goes these days. Fast? Dear God, computers are fast, and software development is also fast compared to the past. But as I code web apps, I keep finding new corners of the browser I didn’t know well. Things are just…wild in there.&lt;/p&gt;&lt;ul&gt; &lt;li&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API&quot;&gt;Web Crypto API&lt;/a&gt; is a first-class security platform in the browser.&lt;/li&gt; &lt;li&gt;The &lt;a href=&quot;https://webassembly.org&quot;&gt;Web Assembly&lt;/a&gt; platform lets you run native-speed code in your browser.&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API&quot;&gt;WebGL&lt;/a&gt; provides for high-quality 3D and 2D graphics in your browser.&lt;/li&gt; &lt;li&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API&quot;&gt;Web Audio API&lt;/a&gt; lets you mix sound in your browser.&lt;/li&gt; &lt;/ul&gt;&lt;p&gt;And on and on. The web is really the greatest distribution platform imaginable right now. It’s inherently multilingual—I released TinyLittleOffice in 21 languages (the most common NYC ones, which is why it has Creole and Yiddish), with lots of infrastructure for accessibility. Plus, of course, JavaScript is a full-featured programming language, and HTML can represent most things a document can do on a computer; if you need something more old-school, &lt;a href=&quot;http://pdf.js&quot;&gt;PDF.js&lt;/a&gt; lets you deal with PDFs in the browser. I think you can even hyphenate text reliably these days, although I refuse to believe it.&lt;/p&gt;&lt;p&gt;I knew these things existed. I’d even programmed with them. But I’d never really looked closely; I just downloaded whatever open-source code would make it easier to build and tried to drag software across the finish line.&lt;/p&gt;&lt;p&gt;My quirky 1990s-vintage office suite might not convince you—it’s weird and small. So take a look at Simon Willison’s new web-based browser 3D game, &lt;a href=&quot;https://simonw.github.io/battledrones/&quot;&gt;Battle Drones&lt;/a&gt;. He’s hosting it on GitHub. He wrote it himself. He’s not a games builder. It just pops right up in the browser and you play it. It’s multiplayer, and it works offline.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://ftrain.com/art/uploads/aboard-newsletter/the-web-is-more-than-enough-1.png?w=1200&quot; alt=&quot;Screenshot from the Battle Drones game featuring a shot of a greenish land mass and several blue and grey structures as pictured from above.&quot; title=&quot;&quot;/&gt;&lt;figcaption&gt;Time to place your Fab Plant.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;As &lt;a href=&quot;https://simonwillison.net/2026/Oct/20/battledrones/&quot;&gt;he wrote about it&lt;/a&gt;:&lt;br/&gt;&lt;/p&gt;&lt;blockquote&gt; &lt;p&gt;… but I can now see a path to vibe coded games like this being taken seriously. Battle Drones is fun, it looks good, it has innovative features (the multiplayer-over-audio thing is a first for an RTS as far as I can tell). I’d love to see what someone with better taste than me and a driving passion to produce something truly exceptional could build!&lt;/p&gt; &lt;/blockquote&gt;&lt;p&gt;All the various cool browser technologies have been around for years. But they are each extremely vast. If you get good at Web Audio, you probably don’t have time to get good at Web Crypto and Web Assembly and WebGL. &lt;/p&gt;&lt;p&gt;The reason they were so complex is, basically, because they were built for teams like those at Google, not for individuals. In the past, the web was for people to build web pages—and, yes, in the present, you can still do that, but for more than a decade, the web has been designed for giant companies so they can deliver software securely to billions of people who buy things with credit cards. These huge mega-libraries were dropped into the web browser to enable large teams to build big things, and the little guy was a bit of an afterthought. But now you can make a game in 3D with sound, and it can work just fine on a plane.&lt;/p&gt;&lt;p&gt;This is one of the places where “are we in an AI bubble” gets fuzzy for me, because it’s totally clear all these giant AI companies are huffing AGI paint fumes, but at the same time, if we actually unlocked the economic transformation of, say, 100 times as many people making software for each other, that would blow an enormous crater into the current tech economy. Don’t like the way your giant industrial looms make carpet? Hack your own firmware and make each carpet totally personalized! Turn any Instagram post into a huge floor covering! Suddenly all the carpet companies have to hack their own firmware to compete. What’s that going to be like? &lt;/p&gt;&lt;p&gt;This also destabilizes the app store economy. The high tax of building for app stores seems less worth paying when you can just test an idea in the world from a web server for $0 after a couple weeks. Perhaps Mozilla should take another swing at launching a mobile phone! (Forget I mentioned that.) In any case, what used to be a large industrial process is now a personal one, if you so desire. Web browsers enable incredibly rich app development—and that’s radically easier than it used to be.&lt;/p&gt;&lt;p&gt;It’s a mixed blessing. I’ve been a writer for years, and software development feels more and more like writing to me every passing week. The awkward part of the comparison is, in general, people do not want to pay writers any money at all. As a writer, you get used to it. But for software people, being perpetually devalued is pretty novel. Then again, if you need software to do something—like our clients!—say, to fix a process, organize a database, get more value out of a big piece of industrial equipment, it’s a pretty amazing time, because you can do just about anything. I’m pretty confident we’ll all meet in the middle, but it’ll take a while, and it will be different on the other side.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>被高估的「行胜于言」 – So!azy</title>
<link>https://blog.solazy.me/20261107/</link>
<enclosure type="image/jpeg" length="0" url="https://bear-images.sfo2.cdn.digitaloceanspaces.com/sol/hannah-busing-zyx1bk9mqma-unsplash-1.webp"></enclosure>
<guid isPermaLink="false">wMUoMHkwaGeclff-e5UsSvl8nLHLSP23XuYHuw==</guid>
<pubDate>Sun, 08 Nov 2026 18:09:20 +0000</pubDate>
<description>今天说个看似和我之前写过文章相悖的选题</description>
<content:encoded>&lt;h1&gt;被高估的「行胜于言」&lt;/h1&gt;&lt;p&gt;
            &lt;i&gt;
                &lt;time&gt;
    07 Nov, 2026
&lt;/time&gt;
            &lt;/i&gt;
        &lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://bear-images.sfo2.cdn.digitaloceanspaces.com/sol/hannah-busing-zyx1bk9mqma-unsplash-1.webp&quot; alt=&quot;hannah-busing-Zyx1bK9mqmA-unsplash&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;前两天和一位朋友吃饭，席间她跟我倒了一肚子苦水。&lt;/p&gt;&lt;p&gt;前阵子她手头有个跨部门协作的项目，推进过程中出了点岔子。她属于那种典型的实干派，发现问题后没在群里多废话，自己连着熬了 2 个通宵，把缺口的数据一点点补齐，赶在节点前把方案救了回来。但在那几天里，面对合作方在群里的频频追问，正在气头上的她只冷冰冰地回了一句「在改了，催也没用」。反倒是项目组里另一个平时素来擅长摸鱼的同事，全程没改过一行字，却每天早晚 2 次在群里发长段文字，态度极其诚恳地向合作方同步「我们非常重视」「已经在通宵抢进度」「一定给各位一个满意的交代」。&lt;/p&gt;&lt;p&gt;等项目顺利上线后，合作方的负责人在复盘会上公开致谢，话里话外都在夸那个摸鱼的同事靠谱、有担当、沟通体验极佳；轮到我这位朋友时，对方只是客套地点了点头，会后还私下跟她领导委婉地提了一嘴，说她脾气有点冲、配合度不够高。&lt;/p&gt;&lt;p&gt;听她吐槽完，我拿着筷子愣了一会儿。要是放在 1 年前，我大概会跟着她一起骂合作方眼瞎、分不清大小王。毕竟她才是那个真正把雷排掉的人，而那个同事除了动动嘴皮子，实质性的贡献几乎为 0。&lt;/p&gt;&lt;p&gt;我最早在博客写&lt;a href=&quot;https://blog.solazy.me/20251103/&quot;&gt;《渣男理论》&lt;/a&gt;那篇文章时，核心观点就是劝大家在人际交往中做成本核算：不要看一个人嘴上说了什么，因为甜言蜜语、陪伴感和口头承诺的边际成本极低；你要看他实际做了什么，看他在需要付出真实的时间、资源和责任时，有没有往后缩。后来在[&lt;a href=&quot;https://blog.solazy.me/20260713/&quot;&gt;《渣男理论 II》&lt;/a&gt;里我也聊过类似的延伸，就是警惕那些用廉价的「你真厉害」来敷衍你、却不肯花心思理解你真实观点的低成本沟通。&lt;/p&gt;&lt;p&gt;那套逻辑在客观事实上依然成立。但我最近越来越意识到，当时我漏掉了一个更残酷的现实前提：真正能够跳过语言、直接去审视行为成本的人，在现实里少之又少。&lt;/p&gt;&lt;p&gt;又或者说，这根本就不是一个人「能不能认知到」的问题，而是人际关系在运转时，天然就有一套先后顺序。在绝大多数日常交往和协作里，人们真正先看到的、先接收到的，永远是一个人「说了什么」。至于他「做了什么」，往往需要漫长的时间周期、极高的观察成本，甚至要等到某次合作彻底崩盘之后，才会被大家后知后觉地意识到一个人到底做得到什么、做不到什么。&lt;/p&gt;&lt;p&gt;我后来仔细想了想为什么会这样。其实原因没那么复杂，做一件事，它的过程是隐蔽的、滞后的、也是没有声音的。就像我那位朋友在电脑前熬夜补数据，合作方看不见她凌晨 3 点还亮着的屏幕，也看不见她推翻重来的那几版草稿。在最终结果交付之前，「做」在别人的视野里几乎处于隐身状态。对方唯一能感知到的触点，就是微信群里那个冷冰冰的对话框。&lt;/p&gt;&lt;p&gt;但「说」不一样。语言是即时的、高颗粒度的、也是自带情绪温度的。人际交往在最初的 80% 时间里，本质上不是价值的交换，而是确定感的交换。当一个人在事情还没着落的时候，先通过语言把态度端出来、把别人的焦虑安抚好、把预期管理住，他在对方心里就已经率先完成了「靠谱」的建档。哪怕他后面实际只做到了 50 分，别人也会顺着他前面立下的好印象，自动帮他找补剩下的 50 分。&lt;/p&gt;&lt;p&gt;反过来，如果你死守着「行胜于言」的信条，闷头把事情做到 90 分，但在嘴上给人喂了颗钉子，那别人第一时间接收到的信号就是冒犯和失控。在你的工作成果展现出来之前，关系就已经先一步结冰了。等到关系冷掉之后，你后来交出来的那份 90 分答卷，在对方眼里也不过是「本来就该交付的分内事」，甚至连挽回印象的筹码都算不上。&lt;/p&gt;&lt;p&gt;所以人际交往里有一条非常反常识的逻辑：决定一段关系走向的，不是你做了什么，而是你说了什么。&lt;/p&gt;&lt;p&gt;想明白这一点之后，我并没有因此觉得那种「纯靠嘴皮子邀功」的做法值得学习。在需要长期深度绑定的关系里，只说不做的人迟早会露馅，依然是第一个该被筛选掉的对象。但在大量的日常协作与浅层社交中，我不再像以前那样，带着一种近似道德洁癖的优越感去鄙视「把话说好听」这件事了。&lt;/p&gt;&lt;p&gt;以前我总觉得，把精力花在修饰语言、安抚对方情绪上是一种低效的妥协，只要我活儿干得漂亮，别人自然应该理解我的苦心。现在回头看，这种想法其实挺傲慢的。你不能一边在嘴上拒绝释放友好的信号，一边又要求别人像全知全能的上帝一样，越过你生硬的态度去精准识别你的付出。别人和你认识才几天，没有义务花那么高的时间成本来拆解你的「刀子嘴豆腐心」。&lt;/p&gt;&lt;p&gt;如果「先听人说什么，再慢吞吞地看人做什么」就是人类社交出厂自带的运行机制，那跟这个机制死磕就是最吃力不讨好的做法。&lt;/p&gt;&lt;p&gt;那天饭局最后，我给朋友的建议也很简单：下次再遇到这种事，活儿照样按自己的高标准干，但在群里回消息之前，先把那句「催也没用」删掉，换成「问题已经定位到了，正在补数据，明天上午 10 点前发你新版本」。不需要去演什么热泪盈眶的戏码，但至少得让对方通过你说的字，第一时间听出你是个打算解决问题的人。&lt;/p&gt;&lt;p&gt;把事做好，是留给时间去检验的底牌；但把话说对，你才有机会坐到时间揭晓底牌的那一刻。&lt;/p&gt;&lt;p&gt;
                
                    &lt;a href=&quot;https://blog.solazy.me/blog/?q=daily&quot;&gt;#daily&lt;/a&gt;
                
            &lt;/p&gt;</content:encoded>
</item>
<item>
<title>The web used to belong somewhere – Manu</title>
<link>https://manuelmoreale.com/thoughts/the-web-used-to-belong-somewhere</link>
<guid isPermaLink="false">jfG1mgUgKECfadnZZw3YeABkKav2AJbkBczPFw==</guid>
<pubDate>Sun, 08 Nov 2026 17:48:10 +0000</pubDate>
<description>There are a couple of related ideas I found myself writing about here and there, either on the IRC server or on Quxnet. Ideas and thoughts about what …</description>
<content:encoded>&lt;h1&gt;&lt;a href=&quot;https://manuelmoreale.com&quot;&gt;The web used to belong somewhere&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;There are a couple of related ideas I found myself writing about here and there, either on the IRC server or on &lt;a href=&quot;https://quxnet.net&quot;&gt;Quxnet&lt;/a&gt;. Ideas and thoughts about what the web used to be, how it used to feel, about how things have changed, and what can be done to bring at least some of the old web back.&lt;/p&gt;&lt;p&gt;We often point fingers at the big social media platforms, with their relentless algorithmic curation as the cause for the awfulness of the modern web. Maybe we blame the SEO folks, or the influencers. There’s a multitude of different characters who each played their role in turning the “old web” into “today’s web”. And I’m not going to pretend they didn’t play a role, because they did.&lt;/p&gt;&lt;p&gt;What I am going to argue for, though, is that there’s something else that has contributed a lot more to the changes that we’ve seen over the past few decades, and that’s the fact that the web used to belong somewhere. And I mean that in the physical sense. I’m not the first one to say this; you can find plenty of other posts out there making this exact point. But it’s a point worth repeating.&lt;/p&gt;&lt;p&gt;There was a time when in order to go online you had to physically go to a specific place: a desk in the house, an internet cafe, a computer lab. The web wasn’t always with you, and you were not always in it and with it. You had to go somewhere, do what you needed to do, and then leave.&lt;/p&gt;&lt;p&gt;BRB? AFK? Acronyms from what feels like a distant past. You are never away from the keyboard today, because there’s a phone following you around everywhere all the time. The internet feels exhausting these days because it’s always there. It’s become what feels like an inescapable presence, for better or for worse.&lt;/p&gt;&lt;hr/&gt;&lt;p&gt;I’ve been particularly unhappy over the past few weeks, for a variety of reasons. And one thing I noticed is that every time I’m in a down phase of life, I can go look at my phone usage and it’s inevitably higher than it should be. At least for me, there’s a 1:1 correlation between how good I feel and how much of a presence the phone is in my life. And the phone is just a proxy for the web because browsing is 95% of what I do on my phone, since I don’t game and I don’t have social apps.&lt;/p&gt;&lt;p&gt;And that’s quite ironic considering I make websites for a living. I build for the web, and at the same time, spending more time than necessary on it makes me terribly unhappy.&lt;/p&gt;&lt;p&gt;But it feels different when I can leave the web behind, when I can get up from my chair, leave my desk, and the web is no longer with me. That feels healthier. The problem is that most of the world doesn’t work that way anymore. If you leave and come back, you’ll probably have a hard time catching up with everything that has happened while you were away because everybody else is not taking a break. And so even if we managed somehow to get rid of algorithmic curation and infinite scrolls and all those things, the web would still not feel like the “old web”. Because the web used to belong to a place. It sadly doesn’t anymore.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>The Military Triumphal Arch</title>
<link>https://triumphalarch.com/</link>
<enclosure type="image/jpeg" length="0" url="https://triumphalarch.com/_astro/carousel-01.BAZtdT99_Il9CD.jpg"></enclosure>
<guid isPermaLink="false">-Z2Sv1mucNSHD3ZNcJmH7hGIKopMVV-ic_4kpQ==</guid>
<pubDate>Sat, 07 Nov 2026 10:54:27 +0000</pubDate>
<description>The United States Military Triumphal Arch. A monument to the triumph of the American Spirit.</description>
<content:encoded>&lt;section&gt;&lt;header&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/nav.BZCCnM9E_Zeemst.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/brand-lockup.Mkj5oKUa_Z2kHLNU.svg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/header&gt;&lt;div&gt;&lt;h1&gt;An American Vision&lt;br/&gt;Finally Realized&lt;/h1&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;div&gt;&lt;h2&gt;&lt;span&gt;A Monument To The American Spirit&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;p&gt;For 250 years, Americans have triumphed over war, division, and hardship. Against impossible odds, our people have built a land of liberty where the individual citizen can thrive, prosper, and pursue happiness greater than any other place in the world.&lt;/p&gt;&lt;p&gt;The United States Military Triumphal Arch celebrates America&amp;#39;s first 250 years and stands as a symbol of its next 250. It serves as a solemn entrance to Arlington National Cemetery, honoring the heroes who gave their lives for our freedom, and as a grand gateway to the capital of the nation that has been, and will forever be, the greatest force for freedom and goodness in the history of the world.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;div&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/viewBase.CoAkIAcA_Z1sf8iv.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/carousel-01.BAZtdT99_Z1u8MKT.webp&quot; alt=&quot;A monumental gateway to the nation’s capital&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;figcaption&gt;&lt;span&gt;&lt;span&gt;A monumental gateway to the nation’s capital&lt;/span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;div&gt;&lt;h2&gt;An American Vision&lt;br/&gt;Finally Realized&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;p&gt;A century ago, America envisioned a monument to reconciliation and national unity following the Civil War.&lt;/p&gt;&lt;p&gt;In 1924, the Arlington Memorial Bridge Commission proposed two monumental columns in Memorial Circle, crowned by figures of Victory. One represented the North. The other represented the South. But the columns were never built.&lt;/p&gt;&lt;p&gt;Today, President Donald J. Trump fulfills and expands on this historic civic vision: what began as a celebration of the reconciliation between North and South finds new expression as a celebration of the triumph of the American spirit throughout the full sweep of American history.&lt;/p&gt;&lt;p&gt;The Military Triumphal Arch realizes a century-old ambition for beautiful monumental architecture in Memorial Circle. While such a grand monument was planned and dreamed of by all of America, it was a Dream that never got built because of the onset of the Great Depression of 1929 — But it will get built now.&lt;/p&gt;&lt;p&gt;The Military Triumphal Arch will be an enduring symbol of American Freedom, American Strength, and American Unity. We will fulfill the aspirations of the Great American Patriots who came before us, and whose plans and visions will finally be realized with the start of construction in our 250th year.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;div&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/map.NeAWbwQB_2coBn6.webp&quot; alt=&quot;Aerial site plan of the Military Triumphal Arch at Arlington Memorial Circle&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;div&gt;&lt;h2&gt;&lt;span&gt;A Tribute To Our Heroes&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;p&gt;From the Lincoln Memorial, across Arlington Memorial Bridge, to the hallowed grounds of Arlington National Cemetery, an extraordinary ceremonial axis connects the ideals of the American Republic engraved in stone —with the heroes who fought and died to defend them.&lt;/p&gt;&lt;p&gt;The Military Triumphal Arch honors all who have served our country. It will inspire future generations to build an America worthy of their sacrifice.&lt;/p&gt;&lt;a href=&quot;https://maps.app.goo.gl/t5zUSKnRYWcA27Gp9&quot;&gt;View on map&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;div&gt;&lt;div&gt;&lt;picture&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/portrait.az5MKDxF_1WRK3x.webp&quot; alt=&quot;President Donald J. Trump&quot; title=&quot;&quot;/&gt;&lt;/picture&gt;&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;“This will be the greatest and most beautiful triumphal arch, anywhere in the world.”&lt;/blockquote&gt;&lt;div&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/v2-signature.B5bXh_Fs_2gLEoI.webp&quot; alt=&quot;Donald J. Trump signature&quot; title=&quot;&quot;/&gt;&lt;/div&gt;&lt;p&gt;Donald J. Trump&lt;br/&gt;45th &amp;amp; 47th President of the United States&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;div&gt;&lt;div&gt;&lt;h2&gt;The Future Begins&lt;br/&gt;With a Step&lt;img src=&quot;https://triumphalarch.com/_astro/future-script-shadow.QAKli3XG_2718z4.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/h2&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/future-title-mobile.BWoDJlcS_1ccuhr.svg&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;div&gt;&lt;p&gt;Great nations remember. Great nations also imagine the possibilities of the future.&lt;/p&gt;&lt;p&gt;The Military Triumphal Arch will honor those who founded, built, defended, and transformed this country, while inspiring new generations to carry forward the American promise.&lt;/p&gt;&lt;p&gt;For centuries to come, Americans will walk beneath this monument with our nation’s history behind them and its future before them, remembering the extraordinary nation they inherited and celebrating the freedom they will pass on.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;footer&gt;&lt;div&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/footerBase.DWySNmn4_9qyDR.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/footerMiddle.fkIW2viX_zQq7p.webp&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;img src=&quot;https://triumphalarch.com/_astro/footer.DXaJC9ue_UFC04.webp&quot; alt=&quot;The illuminated Military Triumphal Arch at night&quot; title=&quot;&quot;/&gt;&lt;p&gt;United States Triumphal Arch Foundation&lt;br/&gt;Chairman: Randy Evans&lt;br/&gt;All images are artistic renderings and may not reflect the final design.&lt;/p&gt;&lt;/div&gt;&lt;/footer&gt;</content:encoded>
</item>
<item>
<title>Lippitt-Knoster in Practice (Field Notes for Managing Complex Projects)</title>
<link>https://sharedphysics.com/lippitt-knoster-in-practice-field-notes-for-managing-complex-projects/</link>
<enclosure type="image/jpeg" length="0" url="https://sharedphysics.com/content/images/2025/05/preview.png"></enclosure>
<guid isPermaLink="false">lYLYQx9LtHU3Tyvr8Nw6vnHcQObj4h9TnPr7yQ==</guid>
<pubDate>Fri, 06 Nov 2026 17:05:58 +0000</pubDate>
<description>&quot;Lippitt-Knoster&quot; is one of those things where if you&#39;ve worked with me during the last 10 years, you&#39;ve likely heard me mention it. You might even be reading this because I needed somewhere to point you. In which case, Hi! 👋 The Lippitt-Knoster Model for Managing Complex</description>
<content:encoded>&lt;p&gt;&amp;quot;Lippitt-Knoster&amp;quot; is one of those things where if you&amp;#39;ve worked with me during the last 10 years, you&amp;#39;ve likely heard me mention it. You might even be reading this because I needed somewhere to point you. In which case, Hi! 👋&lt;/p&gt;&lt;p&gt;The &lt;em&gt;Lippitt-Knoster Model for Managing Complex Change&lt;/em&gt; was originally written to describe a way of navigating large organizational shifts, but I’ve found that it’s also useful as a diagnosis tool for any kind of large and long-running project. After all, every project is a &amp;quot;change&amp;quot; in a microcosm. You might not have a complex organizational change to manage every day, but everyone is involved in long-running projects of some size and shape in a company. So that’s what I use it for, and it is useful indeed.&lt;/p&gt;&lt;p&gt;The beauty of the model is that you don’t need an MBA or a special issue of the Harvard Business Review to explain it. It says that any complex project requires six components to succeed, and if one or another is missing, you’ll have some specific and corresponding failure. &lt;/p&gt;&lt;p&gt;It can be summed up in a simple chart but also rewards you with some deeper insights as you apply it:&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://sharedphysics.com/content/images/2026/11/image.png&quot; alt=&quot;&quot; title=&quot;&quot;/&gt;&lt;/figure&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Vision&lt;/strong&gt; is the purpose and endpoint of a project. Vision tells you where you’re going and why. If the vision is missing, there will be &lt;strong&gt;confusion&lt;/strong&gt; about what is being done and why work is happening.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Consensus&lt;/strong&gt; is a team&amp;#39;s agreement and alignment around the vision. If a team lacks consensus, people will not want to do the thing and they will &lt;strong&gt;sabotage&lt;/strong&gt; you.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Incentives&lt;/strong&gt; are the motivation or reasons for why people support the work and prioritize it appropriately. If not everyone is incentivized properly, there will be &lt;strong&gt;resistance&lt;/strong&gt;. Resistance is the passive sibling of sabotage.&lt;/li&gt;&lt;li&gt;The &lt;strong&gt;Action Plan&lt;/strong&gt; is the practical set of steps to get from vision to finish. If you lack an action plan, your team will experience a routine set of &lt;strong&gt;false starts and treadmills&lt;/strong&gt;, which is another way of saying that it will look like work is happening but nothing actually moves forward. You won’t make progress.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Resources&lt;/strong&gt; are the organizational capacity (people, budget, time) needed to accomplish the work. Lacking resources is a close cousin to lacking skills; it leads to &lt;strong&gt;frustration&lt;/strong&gt; in trying to do something you know you&amp;#39;re capable of, but with an unrealistic set of operating constraints.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Skills&lt;/strong&gt; are the ability to do the work necessary to complete the project. If a team lacks the necessary skills, you&amp;#39;ll have a lot of questions around if this work is possible, leading to &lt;strong&gt;anxiety&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Vision, consensus, and incentives are all &lt;strong&gt;Strategic Concerns&lt;/strong&gt;. They involve abstract political work: ideas, relationships, people, and an understanding of the business. The action plan, skills, and resources are all &lt;strong&gt;Tactical Concerns&lt;/strong&gt;. They are focused on the practical details of “how” something gets done.&lt;sup&gt;1&lt;/sup&gt;&lt;/p&gt;&lt;hr/&gt;&lt;p&gt;One mistake I often see people make is to focus primarily on one concern or the other. For example, a product manager or corporate strategist might spend too much time focused on the strategic side of things without understanding if the team or company is able to execute. Consequently, their ability to build consensus will be negatively impacted by not knowing what is possible or probable. Line managers and software engineers typically make the opposite mistake. They focus too much on the ‘how’ instead of the ‘why’. They’ll prove that something is possible and how it can be done, without realizing that sometimes the team or business doesn&amp;#39;t want to do the thing they’re proposing. Neither myopia ends in a successful project.&lt;/p&gt;&lt;p&gt;The order of the model components matters – they flow into each other – but can be managed in either direction. For example: you might start with a vision, build consensus, arrange the right incentives for everyone to act, create a plan, provide adequate resources and timeline to accomplish that plan, and make sure it is staffed with people who have the skills to execute on it. Easy peasy!&lt;/p&gt;&lt;p&gt;You could also navigate the components the other way, working through a series of questions: is something possible? Do skills exist to accomplish the thing? Do those skills (people) have excess capacity that can be allocated to this idea? Can it be done without budget? Can that group of people be small enough that they organically develop their own plans? And if so, are they incentivized to take on this kind of work outside their daily responsibilities? Does it need sign-off from anyone? If you’ve found confirmatory answers along the way, congratulations: you can carve out a secret R&amp;amp;D initiative within your team or your company. (This is also &amp;#39;&lt;a href=&quot;https://www.ebsco.com/research-starters/business-and-management/effectuation-theory?ref=sharedphysics.com&quot;&gt;effectuation&lt;/a&gt;&amp;#39; in practice.)&lt;/p&gt;&lt;p&gt;You can also read the model from the perspectives of both cause and effect. Reading it one way creates a checklist before kicking off any major work: &lt;em&gt;“Here are the six prerequisites for success, are we all set?”&lt;/em&gt; (A causal, prescriptive reading – given starting parameters, what will be the end result?) Reading it backwards turns it into a troubleshooting tool. For example, if someone comes to you mid-project complaining that &lt;em&gt;&amp;quot;We keep going in circles and the team is anxious! What can I do?&amp;quot;&lt;/em&gt; you might look at the model and respond, &lt;em&gt;&amp;quot;Well of course! You don&amp;#39;t have an action plan. Or maybe, it hasn&amp;#39;t been adequately distributed and communicated and people feel that they lack the skills to accomplish something so big. Let&amp;#39;s break it down into manageable pieces that we do have the skills for.&amp;quot;&lt;/em&gt; It’s pretty quick to go between looking at the failure states and looking at the necessary components to diagnose what’s going on with a project. (A diagnostic reading, reasoning backwards.)&lt;/p&gt;&lt;hr/&gt;&lt;p&gt;The model is a fantastic tool for making sense of things. But that leaves the hard work to start after you&amp;#39;ve made sense of things. How do you drive consensus? How do you align folks around a vision? How do you build up skills, or break down big projects into smaller pieces for which skills exist? How do you win resources, or align incentives? &lt;/p&gt;&lt;p&gt;Some of those answers are obvious, but most are not. Many of the answers are best understood as the manifestation of tacit expertise — a ‘feeling’ for the right move in any particular context, a form of expertise that comes from having been around the block a few times. &lt;/p&gt;&lt;p&gt;And like with most tacit expertise, you’ll find that there are no one-size-fits-all answers to any scenario, but there are plenty of good practices and useful observations. &lt;/p&gt;&lt;p&gt;So here are some of mine:&lt;/p&gt;&lt;hr/&gt;&lt;h3&gt;Strategic Concerns&lt;/h3&gt;&lt;p&gt;The most common and important questions that come up after someone lays out a vision are “&lt;em&gt;Why should we do this?&lt;/em&gt;” and permutations around the follow-up details. If you see those questions, that’s “confusion”, which is another way of saying you’ve presented a fantasy instead of a vision (or perhaps, the vision is missing entirely). That’s because many people confuse vision for having a colorful and inspiring imagination, making their picture too colorful, unrealistically grand, or too far off.&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;My experience is that you make more progress by simply providing adequate context and letting people derive their own vision. The art of context is giving people breadcrumbs to get from where you are today to where you want to be in the future, and giving them some good reasons to follow those breadcrumbs with you. There’s nothing more effective than a self-motivated team that thinks they’re the ones who came up with the idea, that they saw what things could be like. &lt;em&gt;That’s&lt;/em&gt; vision.&lt;/p&gt;&lt;p&gt;Similarly, consensus is a straightforward concept, but strangely elusive in most organizations. Any organization beyond a certain age and size will typically have a &amp;#39;minimally viable consensus&amp;#39; while practically being at odds with itself. Departments often turn into silos with their own internal logic for what should happen. Job security encourages teams to think about what’s best for them instead of for the company. And companies don’t do a great job tying “what’s best for the company” with “what’s best for the individuals within, or the communities around”,&lt;sup&gt;3&lt;/sup&gt; which makes most employment mercenary: people naturally find a balance between what they’re paid and how much to care about the thing in question. (In that sense, incorporated businesses are kind of like democracy: a bad choice, but among the best of the options available for coordinating large groups of people to accomplish things.)&lt;/p&gt;&lt;p&gt;Recognizing that, one amateur mistake people make is trying to build consensus in a group setting. It just doesn&amp;#39;t happen that way. You’re either going to have everyone nodding along and afraid to say their piece in front of everyone else, or you’re going to have one guy (and it’s usually a guy – sorry, my dudes) start pulling some “what about”-ism and dragging the conversation into a black hole of details that you never intended to argue about but find yourself frustratingly debating anyway. &lt;/p&gt;&lt;p&gt;In either scenario, the meeting will end without consensus.&lt;/p&gt;&lt;p&gt;In Japanese business culture there is a concept called “nemawashi”, which translates roughly to “tending to the roots” or “laying the groundwork”. It’s a good analogy because the practice of creating consensus requires a lot of political skill, footwork, trust-building, and private conversation. It means giving people space to tell you everything that’s wrong with your idea, finding ways to address those concerns, and making sure everyone is aligned before the alignment actually happens. The group meeting when everyone signs off in agreement should be the result of careful stage management — you should know and have already addressed everyone’s concerns, including second-order effects of how addressing one person’s issues will impact others. &lt;/p&gt;&lt;p&gt;There should be no surprises; it is theater, not improv.&lt;/p&gt;&lt;p&gt;That said, you might not be able to get to consensus. Perhaps your boss wants the “thing” to happen but there’s another department that’s actively against it. Maybe you&amp;#39;re encroaching on their turf, or it will reduce their capacity in some zero-sum resource bucket. Maybe they just have a different perspective on the world and the approaches the business should take. Maybe you&amp;#39;ve wandered into a long-running feud and this project is just one of many different battles being waged. Who knows, people can be both petty and complicated! &lt;/p&gt;&lt;p&gt;If you can&amp;#39;t get their buy-in, they will sabotage it in all sorts of creative ways. Because sabotage and resistance are close cousins and are political (in the sense of not being open conflict), monographs on activism and subterfuge can be read as useful primers. Consider James C. Scott&amp;#39;s &lt;a href=&quot;https://en.wikipedia.org/wiki/Weapons_of_the_Weak?ref=sharedphysics.com&quot;&gt;&lt;em&gt;Weapons of the Weak&lt;/em&gt;&lt;/a&gt; and the OSS&amp;#39;s &lt;a href=&quot;https://dn720702.ca.archive.org/0/items/Simplesabotage/Simplesabotage.pdf?ref=sharedphysics.com&quot;&gt;Simple Sabotage Field Manual&lt;/a&gt; for what kinds of foot dragging, malicious compliance, noncompliance, evasion, sowing confusion, slander, useless meetings, arbitrary hurdles, revisiting decisions, and moving goalposts to expect.&lt;/p&gt;&lt;p&gt;My advice for these scenarios is to try one of two things. Your first option is to get to the bottom of why there is no consensus and figure out if you’re in a position to address that root cause. Often, you’re not in a position to address those things; if you pursue resolution, you’re going to use up a lot of your political capital or burn out trying to get the project moving forward. And success can be fleeting –  projects can continue to be sabotaged even after launch. I once had a project launch only to have all of its resources immediately pulled, forcing its premature death. &lt;/p&gt;&lt;p&gt;Not even chief executives are immune to this; sometimes the solution to a lack of consensus and active sabotage is to simply fire the people in disagreement. (Obviously, use this technique sparingly — you’re scorching the earth.)&lt;/p&gt;&lt;p&gt;So I recommend most people take the second approach, which is to just drop it. Move on. It’s a lost cause. Don’t be the sailor with a bucket trying to dump water off this Titanic. Quitting things and dropping things is a totally acceptable thing to do; life isn’t a video game where you’re striving for 100% completeness on every side quest. Move on to things where you’re actually making a difference.&lt;/p&gt;&lt;p&gt;But let’s say everyone agrees. Now you need to make sure that things are prioritized appropriately. You’re not going to make any progress if this is low on everyone’s priority list. So you incentivize teams and people. &lt;/p&gt;&lt;p&gt;Positive incentives typically work better than negative incentives, but most people are not in a position to offer meaningful (financial) incentives to push a project forward. Instead, you can rely on horse-trading (“if you help me move this project forward, I’ll help with your thing”), you can help people resolve their problems, and you can paint a compelling-enough end-state that people also want to reach that goal with you.&lt;/p&gt;&lt;p&gt;Otherwise, people are going to be resistant, which is a passive form of sabotage: sabotage without commitment, or general apathy. It might not even be malicious. It’s just… well, you’re just one more project for people to care about and work on. Why should they do it above all else? &lt;/p&gt;&lt;p&gt;And more importantly, resistance can turn into sabotage when incentives are not just missing, but misaligned. Misaligned incentives can break consensus when you&amp;#39;re sweating the details. &lt;/p&gt;&lt;hr/&gt;&lt;h3&gt;Tactical Concerns&lt;/h3&gt;&lt;p&gt;Now, let’s say you figured out the strategic bits and you’re working through the implementation portion. Some projects are simple enough that you can just describe what needs to be done, and you can count those requirements on a single maimed hand. We’re not talking about those projects.&lt;/p&gt;&lt;p&gt;Any complex-enough project requires coordination of requirements, dependencies, timelines, people, and other details. I’ve written a bit about those issues in “&lt;a href=&quot;https://sharedphysics.com/everything-is-important/&quot;&gt;When Everything is Important But Nothing Is Getting Done&lt;/a&gt;”, so I don’t want to retread too much ground.&lt;/p&gt;&lt;p&gt;But one thing worth highlighting is how skills and anxiety are coupled, and how to navigate a lack of skills. Any ambitious project is at some point going to run into a lack of skills or prior experience because the work wouldn&amp;#39;t be ambitious if you&amp;#39;d done it before. So in many regards, it is an existential question for any project: are you and your team able to do what needs to be done? If not, you’ll get a very stressed team, or you’ll get a simulacrum of what you expected.&lt;/p&gt;&lt;p&gt;There are ways to compensate for a lack of skills. I rely on three techniques: &lt;/p&gt;&lt;p&gt;First is up-skilling people. Education, mentorship, and training are effective ways to turn juniors into seniors, low-skilled employees into high-skilled employees. While there are a variety of documented techniques for this (see: &lt;a href=&quot;https://commoncog.com/accelerated-expertise/?ref=sharedphysics.com&quot;&gt;accelerated expertise&lt;/a&gt;, &lt;a href=&quot;https://substack.com/@jtpeterson/p-222847463?ref=sharedphysics.com&quot;&gt;tactical decision games&lt;/a&gt;), the caveats are that (a) this typically takes longer than the time-span of a single project and (b) you need to find people who are interested in learning.&lt;/p&gt;&lt;p&gt;So the second technique is atomization: break the requirements into smaller pieces that meet the level of skill available rather than trying to get people to rise to the required level. Instead of making everyone work harder, just make the requirements easier. Instead of asking people to “cut database reads by 50%” or “create a capacity forecasting model for the next 12 months” (where they may not even know where to start), give them smaller tasks and directions for what to do to accomplish that. Point folks in the right direction, explain the what and the why, turn big asks into a series of steps, a recipe to accomplish something. This is in itself a form of teaching, and it is more project-sized (see what I did there?).&lt;/p&gt;&lt;p&gt;The third technique is to roll up your sleeves and contribute. I’ve learned from many effective leaders that there is no work below your pay grade. What makes many great leaders &amp;quot;great&amp;quot; is their willingness to spend extra time doing &lt;a href=&quot;https://www.noidea.dog/glue?ref=sharedphysics.com&quot;&gt;“glue” work&lt;/a&gt;, filling in the holes between roles, and making sure all assumptions are bridged back to real expectations. They are never too good to personally write up a project document, to manage a tracker, to make sure that people are talking to each other. They often know as much or more about the details than subject matter experts, but they don&amp;#39;t needlessly meddle – they support where needed and use gaps as up-skilling opportunities.&lt;/p&gt;&lt;p&gt;Much of the work of compensating for skills gaps is directly translatable into managing budget, time, and effort tradeoffs to navigate the “resources” component of Lippitt-Knoster. And your ability to solve for skills and resources directly translates back into the specific action plan you need to put together. For example: you may decide not to spend $100,000 on a vendor because you can reverse engineer a single feature you need for a project, but you need to add time to the plan for that. &lt;/p&gt;&lt;p&gt;These considerations become &lt;a href=&quot;https://sharedphysics.com/what-should-be-on-the-roadmap/#2-what-business-decisions-are&quot;&gt;a calculus of risks, rewards, and effort&lt;/a&gt;, which in turn underpins the strategic portions that we talked about earlier: sure, &lt;em&gt;you&lt;/em&gt; might think you can lead a team to rebuild the hot new vendor in house in two months, but have you earned organizational political capital to place those chips on the table?&lt;/p&gt;&lt;hr/&gt;&lt;p&gt;So there you have it, Lippitt-Knoster in practice. Lead on! &lt;/p&gt;&lt;hr/&gt;&lt;p&gt;&lt;sup&gt;1 - This grouping is not present in most Lippitt-Knoster model descriptions I’ve come across; it is my own humble contribution. The order I&amp;#39;m presenting it in is also my contribution – the order in Mary Lippit&amp;#39;s original 1987 model is quite different, for reasons I couldn&amp;#39;t discern.&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;&lt;sup&gt;2 - A realistic vision that is too far into the future is its own type of risk – every day presents new opportunities for conditions to change, starting conditions to be led astray. The likelihood of any far-off future has too many compounding variables... too many things have to go right and be true for it to be reliable enough to pin your hopes to.&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;&lt;sup&gt;3 - These things are usually at odds with each other. There&amp;#39;s a big literature about how &amp;quot;equity&amp;quot; is a tool to get employees to care about corporate success, but most startup equity goes to zero; for the average employee, a bonus or a pay raise is more useful. Public company equity presents a different issue: it is dependent on public market behavior, and less on your individual ability to impact it –  being in a public company, you&amp;#39;re likely one of thousands-plus of employees.&lt;/sup&gt;&lt;/p&gt;&lt;div&gt;
&lt;/div&gt;&lt;p&gt;
                    

&lt;/p&gt;&lt;div&gt;
            &lt;h2&gt;Thanks for reading&lt;/h2&gt;
            &lt;p&gt;Useful? Interesting? Have something to add? Shoot me a note at &lt;a href=&quot;mailto:roman@sharedphysics.com&quot;&gt;roman@sharedphysics.com&lt;/a&gt;. I love getting email and chatting with readers.&lt;br/&gt;&lt;br/&gt;You can also sign up for irregular emails and &lt;a href=&quot;https://sharedphysics.com/rss/&quot;&gt;RSS&lt;/a&gt; updates when I post something new.&lt;/p&gt;&lt;br/&gt;
  
            &lt;h2&gt;Who am I?&lt;/h2&gt;
            &lt;p&gt;I&amp;#39;m Roman Kudryashov -- I help healthcare companies solve challenging problems through software development and process design. My longer background is &lt;a href=&quot;https://sharedphysics.com/about-index/&quot;&gt;here&lt;/a&gt; and I keep track of some of my side projects &lt;a href=&quot;https://sharedphysics.com/tag/projects-2/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;br/&gt;
            &lt;p&gt;Stay true,&lt;br/&gt;Roman&lt;/p&gt;
        &lt;/div&gt;</content:encoded>
</item>
<item>
<title>&quot;People Don&#39;t Want To Work Anymore&quot;... duh? – Absurd Pirate&#39;s Internet Blog</title>
<link>https://blog.absurdpirate.com/people-dont-want-to-work-anymore-duh/</link>
<enclosure type="image/jpeg" length="0" url="https://bear-images.sfo2.cdn.digitaloceanspaces.com/absurdpirate/maxresdefault-1072365317.webp"></enclosure>
<guid isPermaLink="false">vIpuoYoNRk5qwKN0UdeYr1SCCsQ5cXqJVBypmg==</guid>
<pubDate>Fri, 06 Nov 2026 17:05:58 +0000</pubDate>
<description>Nobody wants to work, not even you</description>
<content:encoded>&lt;h1&gt;&amp;quot;People Don&amp;#39;t Want To Work Anymore&amp;quot;... duh?&lt;/h1&gt;&lt;p&gt;
            &lt;i&gt;
                &lt;time&gt;
    03 Nov, 2026
&lt;/time&gt;
            &lt;/i&gt;
        &lt;/p&gt;&lt;p&gt;&amp;quot;People don&amp;#39;t want to work anymore&amp;quot; is a dead horse that&amp;#39;s been beaten to the point of glue. Usually uttered by boomer, petite-bourgeoise types who can&amp;#39;t wrap their senile brains around why people don&amp;#39;t want to work at their shitty Arby&amp;#39;s franchise for $7.50/hr in an area where cost of living requires $15/hr.&lt;/p&gt;&lt;p&gt;People who are indignant about people not being employed have got a neoliberal brain worm eating at their frontal lobe. &amp;quot;People don&amp;#39;t want to work anymore&amp;quot;, yeah no shit dude, you just figured that out? Hell I highly doubt YOU even want to work.&lt;/p&gt;&lt;p&gt;This pride in a P-O-S J-O-B for the sake of having one, is a relatively new and invasive concept. For many human societies in history, work was something to avoid where possible. I came across &lt;a href=&quot;https://www.youtube.com/watch?v=9-PbzIuo78s&quot;&gt;this video&lt;/a&gt; from the channel &amp;quot;The Visual Philosopher&amp;quot; and while most of the video talks about how different cultures talked about a life well-spent, I want to focus on the relationship to labor for the sake of this post.&lt;/p&gt;&lt;p&gt;For all the masturbation shit-lipped conservatives do on the ancient Greeks, they&amp;#39;re like the OGs in not wanting to work. Xenophon once said something along the lines of &amp;quot;the manual jobs are scorned and held in low esteem. They ruin the bodies of those who work in them and those who oversee them, forcing them to sit still and remain indoors. Making their bodies soft and their souls weaker&amp;quot;. The word &amp;#39;banausic&amp;#39; meaning mechanical came from the Greek word &amp;#39;banausos&amp;#39;, a derogatory term for laborers. Take an ancient Greek into modern society, and they&amp;#39;d wonder why we turned being wage slaves into a virtue in much of our culture.&lt;/p&gt;&lt;p&gt;There&amp;#39;s the four aims in Hinduism, Dharma (duty), Artha (wealth), Kama (pleasure/joy), and Moksha (liberation). The 4 meant to be kept in balance, however Artha has much overtaken our society. &amp;quot;Stone Age Economics&amp;quot; by Marshall Sahlins spoke of hunter-gatherer societies and how they seemingly worked less than we do. And it would make sense, you only had to do so much to meet your basic needs, so the rest of your day can be allocated to whatever you want. It shifted once we had to start working for a wage to afford our basic needs rather than meeting them ourselves alongside our tribe.&lt;/p&gt;&lt;p&gt;Not everyone needs to work, hell I&amp;#39;d argue not everyone &lt;em&gt;should&lt;/em&gt; work. Work is something that should be a public service because you want to fill a need in your community. People who can doing for people who can&amp;#39;t. You work because of intrinsic motivation. The plumber isn&amp;#39;t indignant against the people who can&amp;#39;t/doesn&amp;#39;t do their own plumbing. So why is the modern worker indignant against the person who doesn&amp;#39;t work?&lt;/p&gt;&lt;p&gt;We look at the people who don&amp;#39;t work like there&amp;#39;s something wrong with them, but in all actuality, I think it&amp;#39;s a form of jealousy. Because if you get people to say they quiet part out loud, they&amp;#39;d admit they&amp;#39;d love to not have to do piss all or be &amp;quot;lazy&amp;quot;. I&amp;#39;d argue that &amp;quot;laziness&amp;quot; doesn&amp;#39;t exist. What we associate with laziness is often a symptom. People aren&amp;#39;t lazy, they&amp;#39;re burnt out, depressed, disabled, just straight up incapable, or a mix of all of it.&lt;/p&gt;&lt;p&gt;You get stuck in this shitloop where you hate being unemployed because you can&amp;#39;t afford shit, but also hate being employed because... well having a job sucks in most cases.&lt;/p&gt;&lt;p&gt;The problem isn&amp;#39;t labor, people will absolutely do labor, the problem is work. The difference is labor is a natural order to obtain what one wants or to contribute to their community. People would be much happier volunteering for various humanitarian projects (mutual aid, housing, etc.) rather than working a typical desk job. While the project manager/business analyst/HR rep/or even IT professional (like myself) earn more, they contribute significantly less to society than the teacher, domestic laborer (i.e house wife/husband), or nurse who make significantly less. One educates the youth, the other is the reason the entire economy can even function to begin with, and the latter breaks their back to save lives.&lt;/p&gt;&lt;p&gt;It&amp;#39;s an interesting phenomenon that I&amp;#39;ve observed that there&amp;#39;s almost a correlation in the more a position contributes to society the less they&amp;#39;re paid. The jobs that pay the most don&amp;#39;t contribute much to society or their communities, they contribute to the business that exploits it.&lt;/p&gt;&lt;p&gt;I think of when I was a kid and what people wanted to be when they grew up. Most kids my age wanted to be something like a doctor, a firefighter, something of that nature. How many kids want to be a data analyst when they grew up? Probably none. Hell, I wanted to be a therapist when I grew up, I only stopped because I didn&amp;#39;t think it&amp;#39;d make enough money. Well, I got the job that makes enough money, and I fucking hate it. I should have listened to my younger self. Hell the more I learned about social work, the more passionate I am in it as a career/major. So, that’s why I went back to school to earn an MSW.&lt;/p&gt;&lt;p&gt;I personally think wages need to be abolished altogether and things should be done on the basis of doing them. &amp;quot;Oh but then nothing will get done!&amp;quot;, my brother in Christ if money was the only motivator, nobody would be a teacher or contribute to FOSS. We already know intrinsic motivation is the greater motivator than extrinsic motivation, and yet we built our entire socio-economic structure on extrinsic motivation. People would still open up overpriced burger restaurants that play &amp;#39;Stomp, Clap, Hey&amp;#39; music ad nauseum, people would still want to fix plumbing issues in their community, society would still function. It would just operate on a basis of what people really want than what is the most profitable.&lt;/p&gt;&lt;p&gt;That brings the question of progress. What would a society under this model even look like? I&amp;#39;d hypothesize that &amp;#39;progress&amp;#39; would be slower, but more intentional. I think of the Deadpool joke of &amp;quot;you&amp;#39;ll never see a Danish flag on the moon but Goddamnit they&amp;#39;re happy&amp;quot; but societally. Progress would happen to explore more and engage with life deeper. We&amp;#39;d build rockets not for a rich asshole dick-measuring contest, but out of genuine curiosity. There&amp;#39;d be less competing amongst organizations, which would mean more heads together. Think about it, if instead of 10 companies all trying to sabotage and poach each other, you had like 3 regional labor unions you&amp;#39;d have far more people working on one project and would probably get more done.&lt;/p&gt;&lt;p&gt;Anyway, I&amp;#39;m unmedicated for my ADHD right now and have already deleted like 6 paragraphs, so I&amp;#39;m gonna call it here before I go on another tangent. I wanna leave you with this question, if you lived in a moneyless society where your basic needs could be met. What would you want to do? Would you still work the job you have? Or would you do something else?&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blog.absurdpirate.com/fighting-my-inner-completionism&quot;&gt;Previous&lt;/a&gt; | &lt;a href=&quot;https://blog.absurdpirate.com/lets-not-throw-a-party-just-yet&quot;&gt;Next&lt;/a&gt;&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Reply via email: &lt;a href=&quot;mailto:me@absurdpirate.com&quot;&gt;me@absurdpirate.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;hr/&gt;&lt;h3&gt;as of writing this...&lt;/h3&gt;&lt;div&gt;
As mentioned in my last paragraph, I stopped taking Wellbutrin. I cold turkey&amp;#39;d it which probably wasn&amp;#39;t my best idea, but I haven&amp;#39;t been having anything above a minor side effect, so I figured fuggit. I stopped because while it &amp;#39;works&amp;#39; I&amp;#39;ve been dealing with mild anxiety that has been driving me nuts. I&amp;#39;d rather take a raised heart rate from adderall than a raised heart rate from wellbutrin-induced anxiety. So, in the meantime until I get an appointment with my primary care on the 1st, I&amp;#39;ve just been self-medicating on caffeine like I&amp;#39;m in my late-teens/early-20s again. Mrs. Pirate got a new espresso machine as a birthday gift from my mom and step-dad, and I&amp;#39;ve been reaping the benefits. I think I had 4 shots of espresso just yesterday alone and it did as much for me as my regular dose of wellbutrin. I kinda just hate taking pills, more just the sensory aspect of it. I hate the feeling of having to swallow a pill every morning, first thing in the morning. I guess it&amp;#39;s a good thing meds aren&amp;#39;t ingested in the form of a delicious smoothie or something, because no doubt would people just straight up overdose.
&lt;/div&gt;&lt;p&gt;
                
                    &lt;a href=&quot;https://blog.absurdpirate.com/blog/?q=2026&quot;&gt;#2026&lt;/a&gt;
                
                    &lt;a href=&quot;https://blog.absurdpirate.com/blog/?q=socialcommentary&quot;&gt;#socialcommentary&lt;/a&gt;
                
            &lt;/p&gt;</content:encoded>
</item>
<item>
<title>The art of bothering – Herbert Lui</title>
<link>https://herbertlui.net/the-art-of-bothering/</link>
<guid isPermaLink="false">NmsDBvXO0DnWp5kZaORSBzWSmlrPr7id-LHqIQ==</guid>
<pubDate>Thu, 05 Nov 2026 20:59:54 +0000</pubDate>
<description>At one point or another, we all feel lonely. But this tendency has gotten so bad recently that it’s described as a “loneliness epidemic.” Imagine this: you want to meet with a friend, but don’t want to be a bother because you know they’ve got a lot of commitments, you might talk yourself out of […]</description>
<content:encoded>&lt;p&gt;At one point or another, we all feel lonely. But this tendency has gotten so bad recently that it’s described as a “&lt;a href=&quot;https://www.gse.harvard.edu/ideas/usable-knowledge/24/10/what-causing-our-epidemic-loneliness-and-how-can-we-fix-it&quot;&gt;loneliness epidemic&lt;/a&gt;.”&lt;/p&gt;&lt;p&gt;Imagine this: you want to meet with a friend, but don’t want to be a bother because you know they’ve got a lot of commitments, you might talk yourself out of it. There’s a good chance that they’re worried about not wanting to bother you, and so &lt;a href=&quot;https://herbertlui.net/dont-wait-to-get-asked/&quot;&gt;they won’t ask&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Or, you &lt;a href=&quot;https://herbertlui.net/make-your-place-interesting/&quot;&gt;attend an event where you don’t know anyone&lt;/a&gt;, but don’t want to bother people in and interrupt their conversions so you stand by the wall and check your phone.&lt;/p&gt;&lt;p&gt;Or, you want to meet more people, but don’t want to &lt;a href=&quot;https://herbertlui.net/meeting-people-with-cold-emails/&quot;&gt;bother them with a cold email&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Bothering is precisely the most useful thing you can do in these situations. The word “bother” likely comes from the Scottish word “pother,” which means “to make a &lt;a href=&quot;https://herbertlui.net/stir-the-pot/&quot;&gt;stir&lt;/a&gt; or commotion, bustle.” It’s also possible it descends from the English word “pother,” which means “to poke, prod.” &lt;/p&gt;&lt;p&gt;When you take initiative, you also bother. Notice how when you give up on something or shut down a possibility, you say, “Why bother?” &lt;/p&gt;&lt;p&gt;Bothering doesn’t need to be annoying. There’s an art to bothering. You and I are constantly bothered by other people, and we occasionally walk away from it feeling better from the experience. The key to the art is making sure someone else feels glad that you bothered them. Here are some guidelines that might be useful:&lt;/p&gt;&lt;p&gt;It’s useful for your first bother to involve getting someone’s permission. Small talk is a useful way to bother people you don’t know.&lt;/p&gt;&lt;p&gt;Spread your efforts amongst many people, and you won’t be annoying. Focus your efforts on bothering one person, and you may be perceived as extremely annoying. &lt;/p&gt;&lt;p&gt;If you’ve followed up with someone more than three times to silence, let it go. Maybe you can bother them in six months, or a year. But not today. The art of bothering requires &lt;a href=&quot;https://herbertlui.net/restraint/&quot;&gt;restraint&lt;/a&gt;. (These days, I follow up once.)&lt;/p&gt;&lt;p&gt;Master the art of pleasant conversation. When I was a university student, I did a very brief field sales gig for a marketing agency. It involved showing students a laptop and their client’s new software, listening to the students’ feedback, and asking them to fill in a survey. It felt incredibly difficult (and against my nature) to interrupt another student and ask for time. Once I got their permission and we started the conversation, though, things went smoothly. I was even once complimented for &lt;a href=&quot;https://herbertlui.net/thanks-for-reaching-out/&quot;&gt;how pleasant the conversation was&lt;/a&gt;. I eventually quit the gig because I found writing came much more naturally to me, but it became a formative experience.&lt;/p&gt;&lt;p&gt;People feel good when they see an opportunity and &lt;a href=&quot;https://herbertlui.net/helping-feels-better-when-you-want-to-help/&quot;&gt;can offer to help&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Develop a thick skin for being ignored, and know &lt;a href=&quot;https://herbertlui.net/top-of-mind/&quot;&gt;how to stay top of mind&lt;/a&gt; in a more passive way. My wife and I recently &lt;a href=&quot;https://herbertlui.net/notes-on-adopting-a-dog/&quot;&gt;adopted a dog&lt;/a&gt;, who is very food motivated. Whenever we eat, she comes over, puts on her cutest face, and sits down. If we don’t feed her after a few minutes, she lies down a bit further, but constantly keeps an eye on us. I’ve recently learned that dogs can eat bananas and apples in small dosages, because she has bothered me into doing research and feeding her. My dog has mastered this skill in the art of bothering.&lt;/p&gt;&lt;p&gt;Don’t talk yourself out of something just because you’re worried about being annoying. (&lt;a href=&quot;https://herbertlui.net/what-annoys-you/&quot;&gt;You might inspire someone&lt;/a&gt;!)&lt;/p&gt;&lt;p&gt;If, after you bother them, you get the feeling you’ve been bothersome (or someone visibly shows frustration or gives you verbal feedback), you need to show more restraint in how you communicate. Learn from the experience and make sure to let things cool. Maybe you should let them bother you instead.&lt;/p&gt;&lt;p&gt;I wrote all of this for people who worry they are being too much of a bother, so they can learn to bother in a useful way. This post isn’t an excuse to be annoying.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>别让自己变成祥林嫂 – So!azy</title>
<link>https://blog.solazy.me/20261103/</link>
<enclosure type="image/jpeg" length="0" url="https://bear-images.sfo2.cdn.digitaloceanspaces.com/sol/nik-zydyz7jleve-unsplash-1.webp"></enclosure>
<guid isPermaLink="false">elTbq3Ecj6qziZbxHtJxu3DqKbRJak5YKjf-9A==</guid>
<pubDate>Wed, 04 Nov 2026 10:05:19 +0000</pubDate>
<description>怎么办，我现在越来越冷血，越来越提供不了情绪价值了</description>
<content:encoded>&lt;h1&gt;别让自己变成祥林嫂&lt;/h1&gt;&lt;p&gt;
            &lt;i&gt;
                &lt;time&gt;
    03 Nov, 2026
&lt;/time&gt;
            &lt;/i&gt;
        &lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://bear-images.sfo2.cdn.digitaloceanspaces.com/sol/nik-zydyz7jleve-unsplash-1.webp&quot; alt=&quot;nik-zYdYz7JlevE-unsplash&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;前两天有个认识挺久的朋友找我聊天，前前后后发了十几条长消息，全是在吐槽最近工作和生活里的一地鸡毛。&lt;/p&gt;&lt;p&gt;老实说，看着屏幕不断弹出的对话框，我脑子里冒出来的第一个念头居然是：我今天到底要在这些信息上消耗多少时间？或许是我这几年真的变得越来越理性，甚至有点冷血了，我已经很难再像年轻时候那样，毫无保留地去充当别人的情绪垃圾桶。&lt;/p&gt;&lt;p&gt;我当然明白对方找我聊这些，首要诉求是让我提供「情绪价值」。如果是平时珍视的关系，给点适当的安慰、站在他那边骂两句，这都没问题。我愿意为值得的人支付这部分心力，但我毕竟不是什么情绪价值大师，不可能无休止地供应这种廉价的安抚。&lt;/p&gt;&lt;p&gt;在我看来，单纯的情绪价值在很多时候其实就是一种止痛剂，甚至是致幻剂。它能让人在倾诉的半个小时里觉得自己被理解了、委屈被看见了，然后呢？第二天醒来，那个让人痛苦的处境依然原封不动地杵在那里。真正让人难受的问题本身是需要被解决的，而不是被反复咀嚼。&lt;/p&gt;&lt;p&gt;所以听完第一轮发泄之后，我本能地想帮他把事情往前推一步，看看能不能拆解一下现状，或者给点实际的建议。但当我顺着他的话往下问的时候，却发现根本无从下手。&lt;/p&gt;&lt;p&gt;他的抱怨太表面了。全都是「我们领导真是个傻逼」「这破事真让人崩溃」「我觉得太累了」这类纯情绪的宣泄。既没有事情的来龙去脉，也没有双方的利益冲突点，更没有他自己目前握有的牌和底线。我顺着对话框往上翻了半天，找不到任何一个可以切入的受力点。&lt;/p&gt;&lt;p&gt;聊到最后，我只能敲出一句：「然后呢，你跟我说这些，最想表达的是什么？或者你想让我帮你做什么？」&lt;/p&gt;&lt;p&gt;这句话发出去，空气往往就会突然安静下来。在很多人眼里，这种反问简直是标准答案级别的「冷血 T 人」发言，极其扫兴。但我后来琢磨了一下，我真正排斥的其实不是朋友向我抱怨，而是那种彻底放弃了主动权、纯粹为了重复痛苦而存在的单向倾倒。&lt;/p&gt;&lt;p&gt;鲁迅笔下的祥林嫂为什么到了最后会让周围的人感到厌烦甚至恐惧？并不是因为她的遭遇不值得同情，恰恰相反，她最初的悲剧是极其沉重的。但当她把「我真傻，真的」变成一套固定的、不需要任何反馈、也绝不打算通过行动去改变现状的脚本时，倾听者就会敏锐地意识到一件事：你在这段对话里无论给出什么回应，都是无效的。她不需要出路，她只需要一个活人站在面前，配合她完成这场名为「受苦」的循环演出。&lt;/p&gt;&lt;p&gt;成年人之间的深度沟通，本质上是一场需要双方共同出力的协作。你带着麻烦来找我，哪怕你现在脑子很乱，不知道怎么解决，这都很正常。但如果你希望这段对话不只是停留在互相叹气，那你在倒苦水的同时，至少得试着给我留一个「抓手」。&lt;/p&gt;&lt;p&gt;什么是抓手？就是除了告诉我「我很难受」之外，顺便告诉我事实的边界在哪里。比如你现在卡在哪个具体的决策上，你试过了哪 2 种办法但没走通，或者你现在有 A 和 B 两个选项，不知道怎么选。哪怕你直接说「我已经决定辞职了，就是来找你骂街解闷的」，这也是一个清晰的界定，那我就痛痛快快陪你骂完这 15 分钟，然后各自散会去忙正事。&lt;/p&gt;&lt;p&gt;怕就怕那种既不愿意交代真实的背景信息，也不打算为自己的处境做任何切割，甚至连「我到底想要什么结果」都没想过的人。他们把所有的精力都用在了描绘痛苦的质感上，一旦你试图去触碰那个制造痛苦的病灶，他们就会迅速缩回去，甩出一句「你根本不懂我的难处」，然后继续开启下一轮一模一样的抱怨。&lt;/p&gt;&lt;p&gt;遇到这种情况，任何解决问题的企图都会像一拳打在棉花上。你投射进去的时间、精力和逻辑思考，瞬间变成了毫无意义的沉没成本。&lt;/p&gt;&lt;p&gt;我现在的精力预算真的很有限，工作里已经有足够多复杂的系统和具体的业务问题等着我去拆解，回到私人生活里，我只想把注意力留给那些真正想要往前走的人。&lt;/p&gt;&lt;p&gt;所以后来我也给自己划了一条线。面对身边的朋友，第一轮的情绪接纳是我作为朋友的本分；但如果到了第二轮、第三轮，对方依然给不出任何事实层面的抓手，只是在原地打转，那我就会主动叫停这段对话。&lt;/p&gt;&lt;p&gt;抱怨本身并不可耻，谁都有扛不住需要透口气的时候。但人不能放任自己沉浸在倾诉的快感里，把抱怨当成逃避具体行动的掩体。当你遇到破事，开口向别人求助或者倾诉之前，不妨先在脑子里问自己一句：我今天说这些，到底是想找个观众看我受苦，还是想找个帮手一起把这页翻过去？&lt;/p&gt;&lt;p&gt;想清楚这个问题，大概是一个人避免自己变成祥林嫂的最低底线。&lt;/p&gt;&lt;p&gt;
                
                    &lt;a href=&quot;https://blog.solazy.me/blog/?q=daily&quot;&gt;#daily&lt;/a&gt;
                
            &lt;/p&gt;</content:encoded>
</item>
<item>
<title>We don&#39;t want decentralized systems, we want small ones | Andros Fenollosa</title>
<link>https://en.andros.dev/blog/7447ecbb/we-dont-want-decentralized-systems-we-want-small-ones/</link>
<enclosure type="image/jpeg" length="0" url="https://img.andros.dev/ir11xUkPhU9USRHjd-o9tsAQ1ao=/600x0/filters:format(avif):quality(85)/https://andros.dev/media/thumbnails/ryoji-iwata-n31JPLu8_Pw-unsplash.jpg"></enclosure>
<guid isPermaLink="false">ILa-ws6NtXUIHk03fz8rgEdpkQUQNVp191bqJg==</guid>
<pubDate>Mon, 02 Nov 2026 17:15:55 +0000</pubDate>
<description>We don&#39;t want distributed systems, we want small systems. It doesn&#39;t matter if they are centralized inside: what matters is that they stay at a…</description>
<content:encoded>&lt;p&gt;We don&amp;#39;t want distributed systems, we want small systems. It doesn&amp;#39;t matter if they are centralized inside: what matters is that they stay at a manageable size. That makes them cheap, easy to maintain and almost free of moderation. One example is tildes, shared Unix servers where every user has their own account. They run on a trusted admin and donations. When they grow too big, more tildes appear. Another example is Friend Camp, a community of friends. It costs about $30 a month, around $1 per person.&lt;/p&gt;&lt;p&gt;Despite being centralized, they feel like the opposite of big platforms. There are no commercial interests and people know each other. It&amp;#39;s like a shoe shop in a small town. The shop can only serve a few customers because there is little space, you know the owner&amp;#39;s name (maybe even his wife&amp;#39;s) and the shelves don&amp;#39;t offer much variety; and yet you know you will be well served and the owner wants you to leave with what is best for you. In a big department store, on the other hand, the staff don&amp;#39;t care whether you come back or not. The owner might be a board of shareholders who only want to maximize profit. Space is unlimited, but there are queues and it&amp;#39;s hard to get help. You don&amp;#39;t even know if the product is what you are looking for, even if it is cheaper. Welcome to economies of scale. Now apply that to centralized systems.&lt;/p&gt;&lt;p&gt;Distributed systems make us feel in control, because resources are shared among all participants. In return, they only ask us to provide the hardware and the time to maintain it. And that is where they clash with what Moxie Marlinspike said: &amp;quot;People do not want to run their own servers&amp;quot; (2022). Maybe we don&amp;#39;t have the time, the money or the knowledge to be a node in a distributed network. Maybe we already have enough with our lives without also having to keep an eye on our mail server. So we end up using a centralized provider inside a distributed system: GitHub or GitLab when we want to use Git, Gmail or Outlook when we want to use email, or WordPress.com or Medium when we want to publish a blog. The small system solves the dilemma without giving up what matters: one person provides the server and the time for everyone else, and the rest only need to trust someone they know. Isn&amp;#39;t that too much load for one person? Not if the community is small. Darius Kazemi, with about 50 active users on Friend Camp, gets on average one moderation request a month.&lt;/p&gt;&lt;p&gt;Take three Mastodon instances as an example: icosahedron.website (about 133 monthly active users), mastodon.technology (about 23,600 accounts) and mastodon.social (about 3.4 million accounts). All three run the same software and the same protocol; the only thing that changes is size. The second one shut down in 2022 because its only admin burned out. The other two are still alive, but for different reasons: the first because it is small, and the third because it has plenty of resources (in 2024, the organization that runs it brought in about 2.19 million euros, almost all of it from donations).&lt;/p&gt;&lt;p&gt;The biggest risk for a volunteer-run community is almost always the same: that whoever maintains it burns out. That is why size is not a detail: it is what keeps the work within what one person can handle. Limiting size with waiting lists, closed registrations or a cap on active users seems counterintuitive, but it works. To grow without burning out, there are only two paths left: raise a lot of money, like mastodon.social, or become a business, like Reddit, X or YouTube. But profit guarantees neither better quality nor better service. My small Forgejo instance is as centralized as GitHub, but it has 10 active users: it has gone down fewer times, it is faster and it costs me pennies a month to run.&lt;/p&gt;&lt;p&gt;Leopold Kohr wrote it in 1957, long before the internet existed: &amp;quot;Wherever something is wrong, something is too big&amp;quot;. Maybe we have spent years asking the wrong question. It doesn&amp;#39;t matter so much whether a system is centralized, federated or distributed. What matters is whether it fits in the hands of someone you can write to when something breaks. Paul Ford, when he said goodbye to tilde.club, put it in writing: &amp;quot;you can, at any time, for very little money and relatively little effort, stand up a tiny digital community that basically belongs to itself&amp;quot;.&lt;/p&gt;&lt;p&gt;So next time you are looking for a place to publish, to host your code or to talk with your friends, don&amp;#39;t ask whether it is decentralized. Ask how many people are inside and whether you know the name of the person who runs it.&lt;/p&gt;&lt;h2&gt;Sources&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://tilde.club/~ford/&quot;&gt;Paul Ford on tilde.club&lt;/a&gt;, the creator of the first tilde (2014). In his 2019 note he hands the server over to new admins, along with a waiting list of 10,000 people.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/message/tilde-club-i-had-a-couple-drinks-and-woke-up-with-1-000-nerds-a8904f0a2ebf&quot;&gt;I had a couple drinks and woke up with 1,000 nerds&lt;/a&gt;, Paul Ford&amp;#39;s account (2014) of how tilde.club was born and the flood of accounts in its first days.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tildeverse.org/&quot;&gt;Tildeverse&lt;/a&gt;, the association of tildes that followed the tilde.club model.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tilde.club/&quot;&gt;tilde.club&lt;/a&gt;, a shared Unix computer funded by its users&amp;#39; donations.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://texto-plano.xyz/&quot;&gt;texto-plano.xyz&lt;/a&gt;, a Spanish-speaking tilde: &amp;quot;seamos pocos pero unidos&amp;quot; (let us be few but united).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://runyourown.social/&quot;&gt;Run your own social&lt;/a&gt;, Darius Kazemi&amp;#39;s guide based on Friend Camp: 50 to 100 active users, one moderation request a month and about $30 a month in costs.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://moxie.org/2022/01/07/web3-first-impressions.html&quot;&gt;My first impressions of web3&lt;/a&gt;, Moxie Marlinspike&amp;#39;s article, the source of the quote &amp;quot;People do not want to run their own servers&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://icosahedron.website/about&quot;&gt;Icosahedron&lt;/a&gt;, a Mastodon instance running since February 2017 with closed registrations.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ashfurrow.com/blog/mastodon-technology-shutdown/&quot;&gt;Dear mastodon.technology community&lt;/a&gt;, the shutdown announcement by Ash Furrow, who ran it alone.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wiki.archiveteam.org/index.php/Mastodon&quot;&gt;Archive Team: Mastodon&lt;/a&gt;, a record of closed instances, including mastodon.technology and its 23,600 accounts.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mastodon.social/about&quot;&gt;mastodon.social&lt;/a&gt;, the largest Mastodon instance, run by the developers of the software themselves.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joinmastodon.org/reports/Mastodon%20Annual%20Report%202024.pdf&quot;&gt;Mastodon Annual Report 2024&lt;/a&gt;, the accounts of Mastodon gGmbH: revenue, costs and moderation of mastodon.social.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wiki.p2pfoundation.net/Breakdown_of_Nations&quot;&gt;The Breakdown of Nations&lt;/a&gt;, Leopold Kohr&amp;#39;s book (1957), the source of the quote &amp;quot;Wherever something is wrong, something is too big&amp;quot;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
</item>
<item>
<title>Prisoner’s Dilemma is a Scam · YokerHood · Aleksei Matiushkin</title>
<link>https://blog.yokerhood.com/real-prisoners-dilemma</link>
<enclosure type="image/jpeg" length="0" url="https://blog.yokerhood.com/og/post-en-real-prisoners-dilemma.png"></enclosure>
<guid isPermaLink="false">k5d7DB6i9-4hWqetYgSuz4oRoms0K3qpZUgeIg==</guid>
<pubDate>Sat, 31 Oct 2026 12:35:03 +0000</pubDate>
<description>The Prisoner’s Dilemma is the most celebrated thought experiment in game theory and, I dare say, one of the most intellectually dishonest constructions in the history of social science. Not because the mathematics is wrong—the mathematics is airtight, as mathematics tends to be when you get to choose the axioms. The fraud is in the premises.</description>
<content:encoded>&lt;p&gt;
  The Prisoner’s Dilemma is the most celebrated thought experiment in game theory and, I dare say, one of the most intellectually dishonest constructions in the history of social science. Not because the mathematics is wrong—the mathematics is airtight, as mathematics tends to be when you get to choose the axioms. The fraud is in the premises.
&lt;/p&gt;&lt;p&gt;
  For those mercifully unacquainted: two criminals are arrested. Each can stay silent (cooperate with the partner) or testify against them (defect). If both stay silent, each serves one year. If one defects while the other stays silent, the defector walks free and the loyal fool serves three. If both defect, both serve two. The “dilemma” is that rational self-interest dictates defection, even though mutual cooperation yields a better outcome for both. The Nash equilibrium is mutual betrayal. Two rational agents, acting rationally, produce an irrational result. Checkmate, humanity.
&lt;/p&gt;&lt;p&gt;
  This story has launched two thousand scholarly articles, several dozen popular books, and at least one documentary narrated in the kind of hushed voice normally reserved for tectonic plate collisions. The problem is that the story has roughly the same relationship to actual human decision-making as a spherical cow has to dairy farming.
&lt;/p&gt;&lt;h2&gt;
  The Outside World, or: Snitches Get Stitches
&lt;/h2&gt;&lt;p&gt;
  The standard formulation contains a clause so brazen that one wonders how it survived peer review. Let me quote: 
  &lt;i&gt;
    “It is assumed that both prisoners have no loyalty to each other, and will have no opportunity for retribution or reward outside of the game.”
  &lt;/i&gt;
&lt;/p&gt;&lt;p&gt;
  Read that again. Slowly.
&lt;/p&gt;&lt;p&gt;
  “No opportunity for retribution or reward outside of the game.” This is not a simplifying assumption. This is the removal of the entire ecosystem in which the decision operates. It is the equivalent of an aerodynamics paper that begins with “assume no air.” You can certainly derive results under such a premise, but you should have the decency not to call them results about flight.
&lt;/p&gt;&lt;p&gt;
  Criminals—actual criminals, the kind who get arrested in pairs and face prosecutors offering Faustian bargains—exist in social networks denser than a neutron star. The reason is not sentimental; it is economic. Criminal enterprise is, at its core, a repeated cooperation game with extremely high stakes, and the networks that survive are precisely those that have evolved mechanisms to make defection suicidal. The Sicilian Mafia did not invent 
  &lt;i&gt;
    omerta
  &lt;/i&gt;
   because Sicilians have a particular fondness for silence. They invented it because organizations whose members rat each other out at the first prosecutorial wink have the life expectancy of a mayfly. Natural selection applies to institutions as ruthlessly as it applies to organisms, and the institution of “snitch freely, suffer no consequences” went extinct before it could leave fossils.
&lt;/p&gt;&lt;p&gt;
  The Japanese 
  &lt;i&gt;
    yakuza
  &lt;/i&gt;
   have 
  &lt;i&gt;
    yubitsume
  &lt;/i&gt;
  —the ritual severing of a finger joint as atonement for disloyalty. The Russian 
  &lt;i&gt;
    vory v zakone
  &lt;/i&gt;
   maintained an entire parallel legal code inside the prison system, one in which cooperation with authorities was punishable by death. These are not colorful cultural footnotes. These are 
  &lt;i&gt;
    equilibrium-enforcement mechanisms
  &lt;/i&gt;
  , evolved over centuries by groups whose survival depended on solving exactly the problem the Prisoner’s Dilemma claims is unsolvable. The game theorist’s model is a world in which these mechanisms have been surgically removed, and the conclusion—“look, cooperation collapses!”—is presented as insight rather than tautology.
&lt;/p&gt;&lt;p&gt;
  Even in the absence of organized crime, the argument holds. Neighborhoods have memories. Prisons have hierarchies. The man who walks free today because he testified will walk the same streets tomorrow, and the streets will know. The cellblock has its own information network, and it is more efficient than most corporate intranets. The notion that the “game” ends when the prison doors open is a fantasy that could only be entertained by someone whose closest encounter with the criminal justice system is a parking ticket.
&lt;/p&gt;&lt;p&gt;
  The iterated version of the Prisoner’s Dilemma partially addresses this objection. When repetition is introduced, cooperation emerges: Robert Axelrod’s celebrated tournament showed that tit-for-tat—cooperate first, then mirror the opponent’s previous move—beats strategies built on pure defection. Nash himself observed, watching Flood and Dresher’s original hundred-round experiment, that Alchian and Williams cooperated far more than the one-shot theory predicted. But here is the thing: 
  &lt;i&gt;
    there is no such thing as a one-shot game in real life.
  &lt;/i&gt;
   Every human interaction is embedded in a web of relationships, expectations, and consequences that extends far beyond the immediate transaction. The one-shot Prisoner’s Dilemma is not a simplification of reality. It is a different planet.
&lt;/p&gt;&lt;p&gt;
  To strip away reputation, future interaction, social networks, and the threat of retribution, and then to marvel at the collapse of cooperation, is approximately as profound as removing the walls from a building and expressing surprise that the roof falls down. The walls were doing the work. The game theorist removed them and then blamed gravity.
&lt;/p&gt;&lt;h2&gt;
  Pride in a Vacuum
&lt;/h2&gt;&lt;p&gt;
  Very well. Let us, for the sake of argument, accept the vacuum. One shot. No future. No retribution. No social network. Two strangers in separate rooms, never to meet again, never to meet anyone who has met the other. A decision, crystalline in its isolation, untouched by any consideration outside the four walls and the ticking clock.
&lt;/p&gt;&lt;p&gt;
  Even here—
  &lt;i&gt;
    especially
  &lt;/i&gt;
   here—the Prisoner’s Dilemma is built on a hidden assumption so fundamental that most treatments never bother to state it: 
  &lt;strong&gt;
    the payoff matrix is complete.
  &lt;/strong&gt;
&lt;/p&gt;&lt;p&gt;
  It is not.
&lt;/p&gt;&lt;p&gt;
  The matrix shows prison sentences. It assigns numbers to years behind bars. What it does not show—what it cannot show, what it deliberately omits—is the weight of the decision on the person making it. The reflection in the mirror on the morning after. The thing you know about yourself that no parole board will ever ask about and no sentence reduction can erase.
&lt;/p&gt;&lt;p&gt;
  For a certain type of person—the type that game theorists call “rational” and the rest of us might describe less charitably—the matrix is indeed complete. The only thing that matters is the number of years. Freedom is good, imprisonment is bad, the conscience is a rounding error. For this person, defection is the dominant strategy, the Nash equilibrium is mutual betrayal, the mathematicians are right, and the world is a grimmer place than it needs to be.
&lt;/p&gt;&lt;p&gt;
  But humans are not uniform in this regard. Pretending otherwise is the second great fraud.
&lt;/p&gt;&lt;p&gt;
  Some people would rather serve three years with a clean conscience than walk free knowing they sent a man to prison for keeping faith. This is not irrationality. It is not “bounded rationality” or “cognitive bias” or any of the other euphemisms that economists reach for when humans decline to behave like their models. It is a 
  &lt;i&gt;
    different utility function.
  &lt;/i&gt;
   The game theorist’s error is not in the algebra; it is in the ontology. They assumed that the payoff matrix—that neat little grid of prison sentences—describes the entire space of consequences. It does not. The matrix is missing a row. The row is labeled 
  &lt;i&gt;
    self-respect.
  &lt;/i&gt;
&lt;/p&gt;&lt;p&gt;
  Let us call this hidden variable 
  &lt;i&gt;
    pride.
  &lt;/i&gt;
   Not pride in the vainglorious sense—not the peacock’s tail, not the Instagram selfie—but pride in the sense of self-regard: the internal cost of knowing that you have done something you consider contemptible. For some people this cost is zero. For others it exceeds any sentence the state can impose. Between these extremes lies the entire spectrum of human character, conveniently erased by the assumption that all players are “rational agents concerned only with minimizing their prison sentences.”
&lt;/p&gt;&lt;p&gt;
  The quantity that interests us is the ratio of pride to rational self-interest—the 
  &lt;i&gt;
    pride/mind
  &lt;/i&gt;
   ratio. Let us call it 
&lt;code class=&quot;code-inline&quot;&gt;ρ&lt;/code&gt;
   (rho). A person with 
&lt;code class=&quot;code-inline&quot;&gt;ρ = 0&lt;/code&gt;
   is the game theorist’s ideal rational agent: a spreadsheet with legs. A person with infinite 
&lt;code class=&quot;code-inline&quot;&gt;ρ&lt;/code&gt;
   is a saint or a fool, depending on your theology. The rest of us live somewhere in between, and the exact location has consequences that the standard Prisoner’s Dilemma refuses to compute.
&lt;/p&gt;&lt;p&gt;
  Let us compute them.
&lt;/p&gt;&lt;h2&gt;
  The Balanced Game
&lt;/h2&gt;&lt;h3&gt;
  The Setup
&lt;/h3&gt;&lt;p&gt;
  In the standard formulation, the payoffs for player A (expressed as negative sentence years—higher is better) are:
&lt;/p&gt;&lt;p&gt;
  Defection dominates: regardless of what B does, A is better off testifying. Against a silent B, testimony yields freedom (0) rather than one year (-1). Against a testifying B, testimony yields two years (-2) rather than three (-3). The logic is impeccable. The premises are what is crippled.
&lt;/p&gt;&lt;p&gt;
  Now let us introduce pride. When a player defects, they incur a psychological cost proportional to 
&lt;code class=&quot;code-inline&quot;&gt;ρ&lt;/code&gt;
  . But—and this is the crucial nuance—the magnitude of that cost depends on what the opponent did.
&lt;/p&gt;&lt;p&gt;
  Betraying someone who trusted you and stayed silent is, for most humans, a heavier burden than mutual betrayal. If both of you defect, you can at least tell yourself 
  &lt;i&gt;
    he would have done the same.
  &lt;/i&gt;
   If you defected while your partner kept faith, there is no such refuge. We capture this asymmetry with a second parameter 
&lt;code class=&quot;code-inline&quot;&gt;γ&lt;/code&gt;
   (gamma), ranging from 0 to 1:
&lt;/p&gt;&lt;ul&gt;
  &lt;li&gt;
    &lt;strong&gt;
      Defecting against a cooperator
    &lt;/strong&gt;
     costs the full 
&lt;code class=&quot;code-inline&quot;&gt;ρ&lt;/code&gt;
     in shame. You betrayed trust.
  &lt;/li&gt;
  &lt;li&gt;
    &lt;strong&gt;
      Defecting against a defector
    &lt;/strong&gt;
     costs 
&lt;code class=&quot;code-inline&quot;&gt;γρ&lt;/code&gt;
     in shame. Discounted by the knowledge that trust was never on the table.
  &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;
  The modified payoff matrix for player A:
&lt;/p&gt;&lt;p&gt;
  When 
&lt;code class=&quot;code-inline&quot;&gt;ρ = 0&lt;/code&gt;
  , this collapses to the standard Prisoner’s Dilemma. When 
&lt;code class=&quot;code-inline&quot;&gt;ρ&lt;/code&gt;
   is large, cooperation dominates. Somewhere between these extremes, the game balances.
&lt;/p&gt;&lt;h3&gt;
  The Derivation
&lt;/h3&gt;&lt;p&gt;
  Suppose B cooperates with probability 
&lt;code class=&quot;code-inline&quot;&gt;q&lt;/code&gt;
  . Player A is indifferent between strategies when the expected payoffs are equal:
&lt;/p&gt;&lt;pre&gt;&lt;code&gt;E[stay silent] = q(-1) + (1 - q)(-3)      = 2q - 3
  E[testify]     = q(-ρ) + (1 - q)(-2 - γρ) = q(2 + γρ - ρ) - 2 - γρ&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;
  Setting these equal:
&lt;/p&gt;&lt;pre&gt;&lt;code&gt;2q - 3 = q(2 + γρ - ρ) - 2 - γρ
   2q - 3 = 2q + q(γ - 1)ρ - 2 - γρ
  -1 + γρ = q(γ - 1)ρ&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;
  Solving for 
&lt;code class=&quot;code-inline&quot;&gt;q&lt;/code&gt;
  :
&lt;/p&gt;&lt;pre&gt;&lt;code&gt;q = (γρ - 1) / ((γ - 1)ρ)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;
  For the game to be 
  &lt;i&gt;
    balanced
  &lt;/i&gt;
  —each player cooperating with probability exactly 1/2—we set 
&lt;code class=&quot;code-inline&quot;&gt;q = 1/2&lt;/code&gt;
   and solve:
&lt;/p&gt;&lt;pre&gt;&lt;code&gt;2(γρ - 1) = (γ - 1)ρ
  2γρ - 2 = γρ - ρ
  γρ + ρ = 2
  ρ(1 + γ) = 2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;
  Which yields the boundary:
&lt;/p&gt;&lt;blockquote&gt;
  &lt;p&gt;
    &lt;strong&gt;
      ρ = 2 / (1 + γ)
    &lt;/strong&gt;
  &lt;/p&gt;
&lt;/blockquote&gt;&lt;h3&gt;
  What This Means
&lt;/h3&gt;&lt;p&gt;
  The formula says: the critical pride/mind ratio depends on how much you discount the shame of mutual betrayal relative to the betrayal of a cooperator.
&lt;/p&gt;&lt;p&gt;
  &lt;strong&gt;
&lt;code class=&quot;code-inline&quot;&gt;γ = 0&lt;/code&gt;
  &lt;/strong&gt;
  —“Betraying a betrayor costs me nothing.” The hardened realist. Full shame for ratting out a loyal partner, none for mutual defection. Here 
&lt;code class=&quot;code-inline&quot;&gt;ρ = 2&lt;/code&gt;
  . Translation: if your self-respect is worth less than two years in prison, you defect. If it is worth more, you cooperate. At exactly two years, you flip a coin.
&lt;/p&gt;&lt;p&gt;
  &lt;strong&gt;
&lt;code class=&quot;code-inline&quot;&gt;γ = 1/2&lt;/code&gt;
  &lt;/strong&gt;
  —“Mutual betrayal stings, but only half as much.” A plausible default for most humans. Here 
&lt;code class=&quot;code-inline&quot;&gt;ρ = 4/3 ≈ 1.33&lt;/code&gt;
  . Your self-respect needs to be worth roughly sixteen months of freedom to make you indifferent.
&lt;/p&gt;&lt;p&gt;
  &lt;strong&gt;
&lt;code class=&quot;code-inline&quot;&gt;γ = 1&lt;/code&gt;
  &lt;/strong&gt;
  —“All betrayal is equally shameful.” The person for whom the act of defection itself, regardless of context, carries the same moral weight. Here 
&lt;code class=&quot;code-inline&quot;&gt;ρ = 1&lt;/code&gt;
  . One year of self-respect against one year of prison. The exchange rate is 1:1.
&lt;/p&gt;&lt;p&gt;
  The full table:
&lt;/p&gt;&lt;pre&gt;&lt;code&gt;γ       ρ = 2/(1+γ)   Meaning
  ──────────────────────────────────────────────────────
  0.00    2.00          Shame only for betraying trust
  0.25    1.60          Mutual betrayal costs a quarter
  0.50    1.33          Mutual betrayal costs half
  0.75    1.14          Nearly as shameful either way
  1.00    1.00          All betrayal equally shameful&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;
  The Three Regimes
&lt;/h3&gt;&lt;p&gt;
  The complete picture has three regimes, governed by 
&lt;code class=&quot;code-inline&quot;&gt;ρ&lt;/code&gt;
   and 
&lt;code class=&quot;code-inline&quot;&gt;γ&lt;/code&gt;
  :
&lt;/p&gt;&lt;p&gt;
  &lt;strong&gt;
&lt;code class=&quot;code-inline&quot;&gt;ρ &amp;lt; 1&lt;/code&gt;
    —Defection dominates.
  &lt;/strong&gt;
   Classical Prisoner’s Dilemma territory. The shame of betrayal, even at full weight, is less than the one-year difference between cooperation and defection. Mind rules. Pride is a footnote. The game theorists are right, for this particular subspecies of human.
&lt;/p&gt;&lt;p&gt;
  &lt;strong&gt;
&lt;code class=&quot;code-inline&quot;&gt;ρ &amp;gt; 1/γ&lt;/code&gt;
    —Cooperation dominates.
  &lt;/strong&gt;
   The shame of defection, even mutual defection, outweighs the material benefit. The “dilemma” ceases to exist; staying silent is strictly preferred regardless of what B does. (Note: when 
&lt;code class=&quot;code-inline&quot;&gt;γ = 0&lt;/code&gt;
  , this threshold is infinite—you cannot be shamed into cooperating against a defector if mutual defection costs you nothing.)
&lt;/p&gt;&lt;p&gt;
  &lt;strong&gt;
&lt;code class=&quot;code-inline&quot;&gt;1 &amp;lt; ρ &amp;lt; 1/γ&lt;/code&gt;
    —Mixed strategy.
  &lt;/strong&gt;
   Neither strategy dominates. A player cooperates against cooperators (the shame of betrayal exceeds the one-year gain) but defects against defectors (the discounted shame is worth less than the one-year saving). In this regime, the equilibrium is a probabilistic mixture, and the balance point—exactly 50/50—sits at 
&lt;code class=&quot;code-inline&quot;&gt;ρ = 2/(1 + γ)&lt;/code&gt;
  .
&lt;/p&gt;&lt;h2&gt;
  The Missing Variable
&lt;/h2&gt;&lt;p&gt;
  The Prisoner’s Dilemma is not wrong. It is a theorem, and theorems are not wrong; they are either correctly or incorrectly derived from their axioms. The derivation is correct. The axioms are the problem.
&lt;/p&gt;&lt;p&gt;
  The first axiom—no outside world—removes the entire evolutionary apparatus that makes cooperation the default rather than the exception in human affairs. This is the axiom that everybody criticizes, and rightly so. The second axiom—the payoff matrix is complete—assumes that prison sentences are the only relevant consequence, which is tantamount to assuming that human beings have no inner life, no self-respect, and no conscience. This is the axiom that almost nobody questions, because it is not stated as an axiom at all. It is smuggled in as a two-by-two grid and accepted without examination.
&lt;/p&gt;&lt;p&gt;
  The arithmetic above shows that the omission is not merely philosophical. It is 
  &lt;i&gt;
    quantifiable.
  &lt;/i&gt;
   For any given shame-asymmetry 
&lt;code class=&quot;code-inline&quot;&gt;γ&lt;/code&gt;
  , there exists a precise pride/mind ratio 
&lt;code class=&quot;code-inline&quot;&gt;ρ = 2/(1 + γ)&lt;/code&gt;
   at which the dilemma dissolves into perfect indifference. Below this ratio, the game plays as advertised. Above it, cooperation is not altruism—it is self-interest, 
  &lt;i&gt;
    properly accounted for.
  &lt;/i&gt;
&lt;/p&gt;&lt;p&gt;
  The question the Prisoner’s Dilemma actually asks is not “will rational agents cooperate?” It is something far more personal and far more interesting: 
  &lt;i&gt;
    how much is your self-respect worth, measured in prison years?
  &lt;/i&gt;
&lt;/p&gt;&lt;p&gt;
  The answer, unlike the dilemma, is not the same for everyone.
&lt;/p&gt;&lt;p&gt;
  That, perhaps, is the real dilemma.
&lt;/p&gt;</content:encoded>
</item>
<item>
<title>I built a forum with no interface, no passwords, made for the terminal | Andros Fenollosa</title>
<link>https://en.andros.dev/blog/b5c8c6aa/i-built-a-forum-with-no-interface-no-passwords-made-for-the-terminal/</link>
<enclosure type="image/jpeg" length="0" url="https://img.andros.dev/RcArganOGQ8BsVDslAOM_HWMbpg=/600x0/filters:format(avif):quality(85)/https://andros.dev/media/thumbnails/nathan-dumlao-ewGMqs2tmJI-unsplash.jpg"></enclosure>
<guid isPermaLink="false">T5crtzmXCxmoIoE4p1oZF1DHPQzeqUirJISwqg==</guid>
<pubDate>Mon, 02 Nov 2026 12:26:38 +0000</pubDate>
<description>I like forums. Debates, questions, answers, opinions, etc. That feeling of an asynchronous community, where answers are thought through and content…</description>
<content:encoded>&lt;p&gt;I like forums. Debates, questions, answers, opinions, etc. That feeling of an asynchronous community, where answers are thought through and content lasts, is what makes the internet an interesting place. That is why I like reading them and taking part in them. But I had never designed or built one. In my spare time I started sketching one, and I ended up building my humble &lt;em&gt;headless&lt;/em&gt;, federated forum, with simple, modern technologies and open standards.&lt;/p&gt;&lt;p&gt;And I learned a lot along the way. A forum looks simple, but it hides the classic problems of any server. Who can do what? How do you tell a moderator from a regular user? What happens when you have to ban someone? How do you stop someone from stealing an account? Roles, permissions, bans and security. I had to solve them one by one, and you don&amp;#39;t learn that by reading.&lt;/p&gt;&lt;p&gt;Let me tell you how I made &lt;a href=&quot;https://git.andros.dev/andros/tyrtulia&quot;&gt;Tyrtulia&lt;/a&gt;.&lt;/p&gt;&lt;h2&gt;A forum with no interface&lt;/h2&gt;&lt;p&gt;The server only offers a solid, documented API. It is REST with hypermedia: the client only knows one route, &lt;code&gt;GET /&lt;/code&gt;, and discovers everything else by following links. Underneath there are some very boring standards:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;RFC 9110: HTTP semantics, with &lt;code&gt;ETag&lt;/code&gt; and &lt;code&gt;If-Match&lt;/code&gt; so edits don&amp;#39;t overwrite each other.&lt;/li&gt;
&lt;li&gt;RFC 9457: errors.&lt;/li&gt;
&lt;li&gt;RFC 7396: partial updates with &lt;code&gt;PATCH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;RFC 6570: URL templates.&lt;/li&gt;
&lt;li&gt;RFC 4287: Atom feeds.&lt;/li&gt;
&lt;li&gt;RFC 9562: UUIDv7 identifiers.&lt;/li&gt;
&lt;li&gt;JSON Schema: validation.&lt;/li&gt;
&lt;li&gt;Server-Sent Events: real-time events.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;There is no web interface, no forms, no advanced authentication systems, no file handling (images, attachments, etc.), and nothing that isn&amp;#39;t strictly needed to read and write messages.&lt;/p&gt;&lt;p&gt;That is why it is so light. It uses between 60 and 70 MB of RAM and about 50 MB of disk. It only needs Python and SQLite to run.&lt;/p&gt;&lt;h3&gt;An API that discovers itself&lt;/h3&gt;&lt;p&gt;How does a client know what it can do? The server tells it with links. Look at the same request, &lt;code&gt;GET /&lt;/code&gt;, made by a guest (simplified):&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
    &amp;quot;name&amp;quot;: &amp;quot;Forum of example.org&amp;quot;,
    &amp;quot;_links&amp;quot;: {
        &amp;quot;self&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;},
        &amp;quot;latest&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/threads&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;},
        &amp;quot;search&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/search{?q,author,in}&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;, &amp;quot;templated&amp;quot;: true},
        &amp;quot;login&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/sessions&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;POST&amp;quot;, &amp;quot;schema&amp;quot;: &amp;quot;/schemas/session&amp;quot;}
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now by &lt;code&gt;alice&lt;/code&gt;, logged in:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
    &amp;quot;name&amp;quot;: &amp;quot;Forum of example.org&amp;quot;,
    &amp;quot;_links&amp;quot;: {
        &amp;quot;self&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;},
        &amp;quot;latest&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/threads&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;},
        &amp;quot;search&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/search{?q,author,in}&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;, &amp;quot;templated&amp;quot;: true},
        &amp;quot;createThread&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/threads&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;POST&amp;quot;, &amp;quot;schema&amp;quot;: &amp;quot;/schemas/thread&amp;quot;},
        &amp;quot;notifications&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/notifications&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;},
        &amp;quot;events&amp;quot;: {&amp;quot;href&amp;quot;: &amp;quot;/events&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;, &amp;quot;type&amp;quot;: &amp;quot;text/event-stream&amp;quot;}
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If I change a route tomorrow, no client breaks, because none of them knew it in advance. They just follow the links the server gives them.&lt;/p&gt;&lt;h2&gt;Why not use one that already exists?&lt;/h2&gt;&lt;p&gt;I know there are very complete free software forums:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.discourse.org/&quot;&gt;Discourse&lt;/a&gt;&lt;/strong&gt;: the most popular one today.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://flarum.org/&quot;&gt;Flarum&lt;/a&gt;&lt;/strong&gt;: PHP with MySQL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://nodebb.org/&quot;&gt;NodeBB&lt;/a&gt;&lt;/strong&gt;: Node.js, with MongoDB, Redis or PostgreSQL. It stands out for real time with WebSockets.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Or the good old classic: &lt;a href=&quot;https://www.phpbb.com/&quot;&gt;phpBB&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;They are all fantastic, but they are designed to be used from a web browser. They also have an ambitious scope. That is ideal for large communities, but too much for a small, light forum.&lt;/p&gt;&lt;p&gt;That said, Tyrtulia doesn&amp;#39;t give up on the browser: it can be indexed by search engines and anyone can read it on the web.&lt;/p&gt;&lt;h2&gt;No passwords&lt;/h2&gt;&lt;p&gt;No OAuth, no OpenID, no sign-up forms. There are two ways to authenticate:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Your Unix user&lt;/strong&gt;: the client talks to the forum through a Unix socket. The operating system tells the forum which user is on the other side. No sign-up, no login. Your user is your account.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSH key&lt;/strong&gt;: the client connects over HTTP and the forum sends it a challenge. The client signs it with your private SSH key and the forum verifies it with your public key.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;There is no registration over HTTP. If you have a Unix user on the server, you already have an account: it is created the first time you connect through the socket. From there you can add your SSH keys to log in from outside. If you don&amp;#39;t have a user on the machine, the administrator creates an account for you with your public key from the command line. On a tilde, having a Unix user is already the invitation.&lt;/p&gt;&lt;p&gt;Easy to use, secure, and no passwords to steal.&lt;/p&gt;&lt;h2&gt;What changes compared to BBJ&lt;/h2&gt;&lt;p&gt;The idea isn&amp;#39;t mine. I was inspired by &lt;a href=&quot;https://github.com/bbj-dev/bbj&quot;&gt;BBJ&lt;/a&gt;, a bulletin board for the terminal built for small communities or clubs (tildes, pubnixes, club servers, etc.). I took its spirit and brought it to my own ground. Still, there are important differences.&lt;/p&gt;&lt;p&gt;First, the foundations.&lt;/p&gt;&lt;div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;BBJ&lt;/th&gt;
&lt;th&gt;Tyrtulia&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;API style&lt;/td&gt;
&lt;td&gt;RPC: everything is &lt;code&gt;POST /api/&amp;lt;endpoint&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;REST with hypermedia (HAL): only &lt;code&gt;GET /&lt;/code&gt; is known&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions&lt;/td&gt;
&lt;td&gt;The client asks (&lt;code&gt;is_admin&lt;/code&gt;, &lt;code&gt;edit_query&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Links that appear or disappear&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;td&gt;Unsalted SHA-256 hash of the password on every request&lt;/td&gt;
&lt;td&gt;No passwords: Unix socket or SSH-signed challenge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Errors&lt;/td&gt;
&lt;td&gt;6 custom numeric codes&lt;/td&gt;
&lt;td&gt;RFC 9457 with a catalog of types&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pagination&lt;/td&gt;
&lt;td&gt;Everything at once&lt;/td&gt;
&lt;td&gt;Cursor based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrency&lt;/td&gt;
&lt;td&gt;The last edit wins, silently&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ETag&lt;/code&gt; and &lt;code&gt;If-Match&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text format&lt;/td&gt;
&lt;td&gt;Custom language (&lt;code&gt;[bold: ...]&lt;/code&gt;, &lt;code&gt;[red: ...]&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Standard Markdown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;db_validate&lt;/code&gt; endpoint&lt;/td&gt;
&lt;td&gt;JSON Schema linked from each form&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;&lt;code&gt;config.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TOML&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;Then, the features I missed.&lt;/p&gt;&lt;div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;BBJ&lt;/th&gt;
&lt;th&gt;Tyrtulia&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reply to a specific post&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;gt;&amp;gt;N&lt;/code&gt; quotes in the text&lt;/td&gt;
&lt;td&gt;Linked replies, with a tree view&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mentions&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notifications&lt;/td&gt;
&lt;td&gt;No (pending since 2017)&lt;/td&gt;
&lt;td&gt;Inbox with replies, mentions and alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real time&lt;/td&gt;
&lt;td&gt;No, you have to poll&lt;/td&gt;
&lt;td&gt;Server-Sent Events, with resume&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit history&lt;/td&gt;
&lt;td&gt;No, editing overwrites&lt;/td&gt;
&lt;td&gt;Full, with diffs and revert&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deletion&lt;/td&gt;
&lt;td&gt;Deletes the row&lt;/td&gt;
&lt;td&gt;Tombstone: numbering is preserved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search&lt;/td&gt;
&lt;td&gt;Each client searches what it has downloaded&lt;/td&gt;
&lt;td&gt;Server-side full text, accent and case insensitive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Feeds&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Atom for the forum and each thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moderation&lt;/td&gt;
&lt;td&gt;Admin or not&lt;/td&gt;
&lt;td&gt;Roles, hidden posts, reports and a public log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rate limiting&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Per user and per IP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;What they share is a small server built on SQLite and several text clients against a documented API.&lt;/p&gt;&lt;h2&gt;Clients&lt;/h2&gt;&lt;p&gt;A &lt;em&gt;headless&lt;/em&gt; forum needs clients, no way around it.&lt;/p&gt;&lt;h3&gt;Tyrtulia TUI&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://git.andros.dev/andros/tyrtulia-tui&quot;&gt;Tyrtulia TUI&lt;/a&gt; is the terminal client, built with Textual.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://img.andros.dev/a68h_x8D3VTyz8p6Y-BoFh0w2Gw=/filters:format(avif):quality(85)/https://andros.dev/media/blog/2026/10/tyrtulia-tui-thread.png&quot; alt=&quot;A thread in Tyrtulia TUI&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;h3&gt;tyrtulia.el&lt;/h3&gt;&lt;p&gt;If you know me a little, you know this package was a must: &lt;a href=&quot;https://git.andros.dev/andros/tyrtulia.el&quot;&gt;tyrtulia.el&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://img.andros.dev/oDU8xw1h26NmhxlC25_EYvrLc3I=/filters:format(avif):quality(85)/https://andros.dev/media/blog/2026/10/tyrtulia-el-thread.png&quot; alt=&quot;A thread in tyrtulia.el&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;h3&gt;Tyrtulia Web&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://git.andros.dev/andros/tyrtulia-web&quot;&gt;Tyrtulia Web&lt;/a&gt; is more a mirror of the content than a client. Its goal is to let search engines index the forum and let anyone read it from a browser.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://img.andros.dev/dGNVvmXPwcmaRRWW0hQQh3SqU7Q=/filters:format(avif):quality(85)/https://andros.dev/media/blog/2026/10/tyrtulia-web-thread.png&quot; alt=&quot;A thread in Tyrtulia Web&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;It has an unstyled theme and another one that mimics my website.&lt;/p&gt;&lt;h2&gt;Federation&lt;/h2&gt;&lt;p&gt;You can connect to one forum or set up several. Federation happens in the clients: servers don&amp;#39;t talk to each other or copy messages between them. Each forum is independent, with its own users, rules and moderators.&lt;/p&gt;&lt;p&gt;Instead of splitting them into tabs or accounts, the clients mix the threads of all of them into a single list.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://img.andros.dev/J9wYL7kquMLlj2nNlNjC1koCw0Y=/filters:format(avif):quality(85)/https://andros.dev/media/blog/2026/10/tyrtulia-el-forums.png&quot; alt=&quot;Three forums in the same list&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;Of course, you can only write in the forums where you have an account. In the rest you can only read.&lt;/p&gt;&lt;p&gt;I think it&amp;#39;s a pretty cool feature, because it keeps the API code much simpler and lets you explore other forums at zero cost.&lt;/p&gt;&lt;h2&gt;Try it&lt;/h2&gt;&lt;p&gt;It has been fun to design and build. Of course there are more complete forums, more powerful federation systems, and even decentralized systems that leave Tyrtulia in the dust (Aether, Nostr...). But its niche is very specific: a light, closed-access, federated, indexable, secure forum with text clients. For everything else, there are better things out there.&lt;/p&gt;&lt;p&gt;If you feel like trying it, the installation guide is in the &lt;a href=&quot;https://git.andros.dev/andros/tyrtulia#getting-started-for-administrators&quot;&gt;Tyrtulia repository&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I look forward to your feedback.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>The upvote dilemma – Herman&#39;s blog</title>
<link>https://herman.bearblog.dev/the-upvote-dilemma/</link>
<enclosure type="image/jpeg" length="0" url="https://bearblog.dev/static/og-image.png"></enclosure>
<guid isPermaLink="false">KWlR4bRigDznPpsjE41_vLZoi2yGtewYObnobg==</guid>
<pubDate>Tue, 27 Oct 2026 18:32:45 +0000</pubDate>
<description>Hiding upvotes on the discovery feed</description>
<content:encoded>&lt;h1&gt;The upvote dilemma&lt;/h1&gt;&lt;p&gt;
            &lt;i&gt;
                &lt;time&gt;
    27 Oct, 2026
&lt;/time&gt;
            &lt;/i&gt;
        &lt;/p&gt;&lt;p&gt;A couple of weeks ago I quietly removed the upvote count from the &lt;a href=&quot;https:bearblog.dev/discover/&quot;&gt;discovery feed&lt;/a&gt; on Bear. The upvote button is still there on every post, and upvotes still decide what ends up on Trending. You just can’t see the numbers next to each post anymore.&lt;/p&gt;&lt;p&gt;I made the change for two reasons.&lt;/p&gt;&lt;p&gt;The first is that visible counts make the popular posts more popular. A post with a lot of upvotes looks like it’s worth reading, so it gets read and upvoted more, and the quiet posts with no audience stay quiet. One of the things I love about Bear, and actively curate, is that someone with no audience can still be discovered. Hiding the count means people judge a post by its title and writing, not by how many people liked it first, especially on the Newest page.&lt;/p&gt;&lt;p&gt;The second is that upvote numbers don&amp;#39;t make people &lt;em&gt;feel good&lt;/em&gt;. Someone puts sincere effort into a post, publishes it, and then sees a little “1” next to it, sitting right below someone else’s “214”. Writing shouldn’t feel like a popularity contest, and a number next to your name makes it one, whether you like it or not.&lt;/p&gt;&lt;p&gt;More broadly, I think the &amp;quot;like button&amp;quot; is one of the things that made the internet worse (that and infinite scroll). It turned writing and sharing into a scoreboard, and it trained a generation of platforms (and people) to optimise for the number instead of the thing itself. I’ve been critical of this in my post on &lt;a href=&quot;https://herman.bearblog.dev/slow-social-media/&quot;&gt;social media&lt;/a&gt;, and it felt a bit hypocritical to have the same mechanic on Bear’s own feed.&lt;/p&gt;&lt;p&gt;Despite my above grievances, upvotes &lt;em&gt;are&lt;/em&gt; useful. They’re a good, simple signal to indicate what people have enjoyed, and I haven’t found a better way to rank the feed (yet). This feels like a decent tradeoff. Upvotes still do the useful job of ranking, but they no longer act as a public scoreboard.&lt;/p&gt;&lt;p&gt;I was a little worried making this change (hence the quiet rollout to test it), since part of the appeal of upvoting is seeing number go up. So I compared the two weeks after the change with the month prior, and the number of upvotes per day didn’t change, the number of people upvoting didn’t change, and neither did the number of people clicking through to posts from the feed. People are reading and upvoting as much as before. They’re just not comparing scores while they do it, and upvotes are spread out among more posts than before. Great success!&lt;/p&gt;&lt;p&gt;It’s still early days, and I’ll keep an eye on it over the next month. But for now the numbers are staying hidden.&lt;/p&gt;&lt;p&gt;If you have thoughts on this, send me an email. I’d love to hear how it feels from your side, both as a reader and as a writer.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>ask me something – yours, tiramisu</title>
<link>https://tiramisu.bearblog.dev/ask-me-something/</link>
<enclosure type="image/jpeg" length="0" url="https://bear-images.sfo2.cdn.digitaloceanspaces.com/tiramisu/img_3535_original.webp"></enclosure>
<guid isPermaLink="false">tBk9XBHqsvMJF2YqYRB1sl1S8ETpnZVm0abLcw==</guid>
<pubDate>Thu, 29 Oct 2026 17:59:22 +0000</pubDate>
<description>A few weeks ago, while talking to A, she told me something about her that surprised me (I can no longer remember what). &quot;I didn&#39;t know that about you!&quot; I...</description>
<content:encoded>&lt;h1&gt;ask me something&lt;/h1&gt;&lt;p&gt;
            &lt;i&gt;
                &lt;time&gt;
    29 Oct, 2026
&lt;/time&gt;
            &lt;/i&gt;
        &lt;/p&gt;&lt;p&gt;A few weeks ago, while talking to A, she told me something about her that surprised me (I can no longer remember what).&lt;/p&gt;&lt;p&gt;&amp;quot;I didn&amp;#39;t know that about you!&amp;quot; I said.&lt;/p&gt;&lt;p&gt;&amp;quot;Well, you never ask me anything,&amp;quot; she said, with a forcefulness that caught me off guard.&lt;/p&gt;&lt;p&gt;It stung. It stung because she was right, and it stung because I know how terrible it feels to be in her shoes. I was simultaneously struck by how brave it was of her to say so and how lucky I was that she had bothered to tell me. If she hadn&amp;#39;t told me, I never would have known.&lt;/p&gt;&lt;p&gt;Later that week, I told B about this on a call. She just nodded, as if she&amp;#39;d known this about me all this time. Then she told me about this date she went on where the guy talked the whole time and never asked her anything. When the date ended he said to B that he thought the date had gone great. (B is a great listener.) B had a less rosy view of the date. Naturally, there was no second date.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Uh oh,&lt;/em&gt; I thought. &lt;em&gt;That must be what it&amp;#39;s like to talk to me.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Today, I was on a walk with J around the neighborhood. We had just reached the top of a big hill when the conversation hit a lull.&lt;/p&gt;&lt;p&gt;&amp;quot;Ask me something!&amp;quot; she said.&lt;/p&gt;&lt;p&gt;I obliged. I told her I was glad she had said so because I hadn&amp;#39;t noticed, and judging from these recent episodes I clearly have an issue with this. Other people must notice this about and simply not tell me. (I don&amp;#39;t blame them — how are you supposed to bring something like this up?)&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://bear-images.sfo2.cdn.digitaloceanspaces.com/tiramisu/img_0724.webp&quot; alt=&quot;IMG_0724&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;I&amp;#39;ve been trying to think about the reasons why I might not ask someone as many questions as they (and I, often) would like.&lt;/p&gt;&lt;p&gt;The least common reason but the one that comes first to mind is that sometimes, I don&amp;#39;t ask questions because I don&amp;#39;t care about the answers. This happens mostly at work. I&amp;#39;ll utter some pleasantries if someone asks about my weekend, and I might even instinctively ask about theirs in return, but I won&amp;#39;t ask more questions because I don&amp;#39;t really want to know any more and because I dislike when people ask me things without caring about the answers. Obviously, this does not apply to any of my friends, so it is not very helpful in diagnosing the aforementioned scenarios.&lt;/p&gt;&lt;p&gt;Far more often, I &lt;em&gt;want&lt;/em&gt; to know things. Of course I worry about how J and B and how all my other friends feel when talking to me. Beyond that, though, &lt;em&gt;I&lt;/em&gt; also lose when I don&amp;#39;t ask questions. Sometimes, I&amp;#39;ll leave long conversations with people and only later think about all these questions I wanted to ask them and didn&amp;#39;t get a chance to.&lt;/p&gt;&lt;p&gt;(This is part of the reason I enjoy written communication so much, whether that be emails or letters or texts: it&amp;#39;s so much easier to ask questions asynchronously! You don&amp;#39;t have to worry about interrupting someone or asking something at the wrong time. If you&amp;#39;re unsure whether a question is appropriate, you have time to think about it. Real-life conversations go faster than my brain can keep up.)&lt;/p&gt;&lt;p&gt;The biggest reason is also the most simple: asking questions is hard. With the exception of the easiest questions, like asking someone where they went when they mention coming back from vacation, there are so many things I have to consider before ask a question. &lt;em&gt;Where do I begin? Which of these things do I want to ask about first? Did they already tell me the answer to this somewhere else? Is this a good question? Is now a good time to ask? Am I prying?&lt;/em&gt; It takes a significant amount of my brainpower to whittle down an amorphous curiosity about the way a person is and their current state into open, coherent, socially acceptable questions.&lt;/p&gt;&lt;p&gt;In the meantime, because they&amp;#39;re my friends, they&amp;#39;re probably asking me thought-provoking questions that make me speak at length, during which all my question-planning goes out the window. When the conversation slows, the planning has to start anew. &lt;em&gt;What do I want to know about the most? How do I phrase this? Wait, have I already asked this? Should I know the answer?&lt;/em&gt;&lt;/p&gt;&lt;p&gt;To help my slow, porous brain, I used to take notes when calling friends, roughly outlining what they had told me and jotting down questions that bubbled up. It&amp;#39;s harder to do this in everyday conversations when you&amp;#39;re having dinner or walking around. I don&amp;#39;t always have pen and paper handy, and some people find it weird if you take notes in casual conversation. For me it helps offload some of the thinking and remembering that a productive conversation demands, especially when there&amp;#39;s a lot to catch up on or when talking to someone new with whom I should mind my Ps and Qs. (B would sometimes wait for me to finish writing stuff down and wait expectantly for a question, of which I usually had a few scribbled somewhere on my legal pad.)&lt;/p&gt;&lt;p&gt;I&amp;#39;ve also realized recently that I feel some internal resistance to posing the questions people ask me back at them. J said for her it was the most natural thing to do. I always find it difficult for some reason. Maybe I think it feels like a lazy response, or I feel some responsibility to lead the conversation in a different direction? I don&amp;#39;t know why, but will keep trying to figure it out.&lt;/p&gt;&lt;p&gt;It&amp;#39;s hard — maybe even impossible — to observe something like this objectively myself. A concept I vaguely remember from high school physics — maybe the observer effect? — talked about how we&amp;#39;ve never been able to observe the natural behavior of an electron because observing it would require us to shine light on it and thus disturb it, causing it to act differently. I can&amp;#39;t act as I normally do if I&amp;#39;m consciously thinking about this, but I can&amp;#39;t pay attention to it if I&amp;#39;m not thinking about it.&lt;/p&gt;&lt;p&gt;One solution, I found myself proposing to J, is that I need someone to record my conversations so I can listen to them back and match up what I said and how I acted to how I remember feeling in the moment. But I can&amp;#39;t know I&amp;#39;m being recorded because that would make me act differently, so one of my friends would have to surreptitiously record me without me noticing. (You have my permission, by the way, provided you send me the recording and promise not to use it for nefarious purposes.)&lt;/p&gt;&lt;p&gt;That sounds like a lot. Instead I suppose I could make a survey for my friends to take and see what they have to say about this. I&amp;#39;d wager some of them (maybe even a lot of them, judging from recent events) have noticed and not told me. I also think, though, that some of my other friends might not feel similarly. In fact, I am sure I ask a few of them far more questions than they ask me.&lt;/p&gt;&lt;p&gt;Which begs the question: what separates the two groups? It&amp;#39;s a matter of space: some people let more time pass in between exchanges. They wait longer and let the silence build. In those in-between moments, I have time to regroup my thoughts, formulate questions, and ask them. I don&amp;#39;t know if these conversations are better as a result — probably not — but they are more balanced in this regard. (To be clear, I don&amp;#39;t want my other friends to get the wrong idea and all of a sudden force me to sit in silence during our conversations. I think I just need to practice getting the balance right.)&lt;/p&gt;&lt;p&gt;On an unrelated note, I love when people talk about the conversation we&amp;#39;re having while we&amp;#39;re in it, or detail their own thought process! Meta-conversation, if you will. Anything from &lt;em&gt;we&amp;#39;re unusually quiet today&lt;/em&gt; to &lt;em&gt;oh, you seemed like you didn&amp;#39;t want to talk about it and I didn&amp;#39;t want to pry&lt;/em&gt;. Acknowledging something like silence or tension makes space in the conversation to unpack said phenomenon. I find that the most growth (personal and interpersonal) growth happens in those moments, when you talk directly about whatever you&amp;#39;ve noticed that hangs in the air like a haze.&lt;/p&gt;&lt;p&gt;Where to go from here? I&amp;#39;m not confident that just being mindful of this shortcoming of mine in conversations is enough to fix it. After all, if it were that easy, would anybody have this problem?&lt;/p&gt;&lt;p&gt;As always, if you have any thoughts or advice, I&amp;#39;d love to &lt;a href=&quot;https://tiramisu.bearblog.dev/contact/&quot;&gt;hear&lt;/a&gt; from you. (You can remain anonymous by filling in a bogus name/email if you wish, though please make it clear so I don&amp;#39;t shoot off a reply to some unsuspecting stranger.) If you came here thinking this would be some AMA, I am sorry to disappoint, though you are always welcome to ask me anything.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://bear-images.sfo2.cdn.digitaloceanspaces.com/tiramisu/img_8342.webp&quot; alt=&quot;IMG_8342&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt; Topical meme. Translation: &lt;em&gt;Simple makeup ! I accept criticism (but I don’t stay quiet, either)&lt;/em&gt; &lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;To end this post, I revisited this old post that feels especially relevant to my situation now, &lt;a href=&quot;https://www.experimental-history.com/p/good-conversations-have-lots-of-doorknobs&quot;&gt;Good conversations have lots of doorknobs&lt;/a&gt;.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Givers think that conversations unfold as a series of invitations; takers think conversations unfold as a series of declarations. When giver meets giver or taker meets taker, all is well. When giver meets taker, however, giver gives, taker takes, and giver gets resentful (“Why won’t he ask me a single question?”) while taker has a lovely time (“She must really think I’m interesting!”) or gets annoyed (“My job is so boring, why does she keep asking me about it?”).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;It&amp;#39;s easy to assume that givers are virtuous and takers are villainous, but that’s giver propaganda. Conversations, like improv scenes, start to sink if they sit still. Takers can paddle for both sides, relieving their partners of the duty to generate the next thing. It’s easy to remember how lonely it feels when a taker refuses to cede the spotlight to you, but easy to forget how lovely it feels when you don’t want the spotlight and a taker lets you recline on the mezzanine while they fill the stage. When you’re tired or shy or anxious or bored, there’s nothing better than hopping on the back of a conversational motorcycle, wrapping your arms around your partner’s waist, and holding on for dear life while they rocket you to somewhere new.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;The crux of the post is that good conversations have affordances, or big doorknobs for other people to grab onto. Doorknobs give other people things to ask about or respond to and continue the conversation. Most of the time, I don&amp;#39;t feel like my conversations with friends lack doorknobs on either side. What stood out as more relevant to my situation was this:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;You might think that the best conversationalists wait patiently for their partners to finish talking before they start concocting a response in their head. &lt;strong&gt;It turns out that we like people the best when they respond to us the fastest — so fast (mere milliseconds!) that they must be formulating their reply long before we finish our turn.&lt;/strong&gt; Abundant affordances allow for this rapid-fire rapport, each utterance offering an obvious opportunity to respond.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;I am not so good at this skill that makes people likeable. When I listen to someone, it takes all of my brainpower to process and absorb what they are saying. If you tell me something complex or important, I might even close my eyes to concentrate. I don&amp;#39;t say this as an excuse, or a cop-out, because I&amp;#39;d very much like to change; I just want people to know that I&amp;#39;m not uncurious about them, only a little slow and trying my best to keep up. Like many other things, it&amp;#39;s a work in progress. ⟡&lt;/p&gt;&lt;p&gt;
                
                    &lt;a href=&quot;https://tiramisu.bearblog.dev/blog/?q=english&quot;&gt;#english&lt;/a&gt;
                
                    &lt;a href=&quot;https://tiramisu.bearblog.dev/blog/?q=friendship&quot;&gt;#friendship&lt;/a&gt;
                
                    &lt;a href=&quot;https://tiramisu.bearblog.dev/blog/?q=wordvomit&quot;&gt;#wordvomit&lt;/a&gt;
                
            &lt;/p&gt;</content:encoded>
</item>
<item>
<title>Free Software, Per Accidens - gingerBill</title>
<link>https://www.gingerbill.org/article/2026/10/28/free-software-per-accidens/</link>
<guid isPermaLink="false">dlK7nf1CFyZ0DdvWQFFlQDt-zXmwNvbbFrZQmA==</guid>
<pubDate>Wed, 28 Oct 2026 23:35:47 +0000</pubDate>
<description>Recently I have been thinking now that LLMs/AI have made it relatively &quot;simple&quot; to decompile just about anything, doesn&#39;t that suggest many of the core &quot;principled/idealistic&quot; arguments for OSS/FOSS were never fundamental to begin with?I know you don&#39;t get back what was actually written, especially with optimized binaries, but that gap keeps shrinking in terms of usefulness. From a philosophical standpoint, doesn&#39;t it show that many (not all) of the foundations of movements like FOSS (especia...</description>
<content:encoded>&lt;header&gt;
&lt;h1&gt;Free Software, Per Accidens&lt;/h1&gt;

&lt;div&gt;
&lt;p&gt;&lt;span&gt;2026-10-28&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/header&gt;&lt;p&gt;Recently I have been thinking now that LLMs/AI have made it relatively “simple” to decompile just about anything, doesn’t that suggest many of the core “principled/idealistic” arguments for OSS/FOSS were never fundamental to begin with?&lt;/p&gt;&lt;p&gt;I know you don’t get back what was actually written, especially with optimized binaries, but that gap keeps shrinking in terms of usefulness. From a philosophical standpoint, doesn’t it show that many (not all) of the foundations of movements like FOSS (especially GNU) were &lt;em&gt;per accidens&lt;/em&gt;⁠&lt;sup&gt;1&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt; &lt;em&gt;Per accidens&lt;/em&gt; means &lt;em&gt;incidental&lt;/em&gt; (a product of circumstance), as opposed to &lt;em&gt;per se&lt;/em&gt;, meaning essential, true by its very nature.&lt;/span&gt;&lt;/span&gt; rather than &lt;em&gt;per se&lt;/em&gt;?&lt;/p&gt;&lt;h2&gt;Origin Stories&lt;/h2&gt;&lt;p&gt;All of this makes me wonder how much of the FOSS movement was just post-hoc justification. Part of the origin story is Stallman being annoyed that he couldn’t get the source for a Xerox printer to add a paper jam notification.⁠&lt;sup&gt;2&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt; Sam Williams, &lt;a href=&quot;https://oreilly.com/openbook/freedom/&quot;&gt;&lt;em&gt;Free as in Freedom: Richard Stallman’s Crusade for Free Software&lt;/em&gt;&lt;/a&gt; (O’Reilly, 2002), chapter 1, “For Want of a Printer”.&lt;/span&gt;&lt;/span&gt; I completely sympathize with the frustration (I still have printer problems to this day), but the origin alone doesn’t prove anything.&lt;/p&gt;&lt;p&gt;The other part of the origin story is Unix being locked behind expensive licences once AT&amp;amp;T could commercialize it. I’m not disputing any of that context. But being a response to circumstances doesn’t make an argument per accidens; depending on those circumstances does.&lt;/p&gt;&lt;h2&gt;Open vs Free(dom)&lt;/h2&gt;&lt;p&gt;Most of the framework of the Free Software Movement still assumes source code is hard to get or that binaries are hard to modify. GNU’s &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html#make-changes&quot;&gt;Freedom 1&lt;/a&gt; (study) even lists access to source as a precondition.⁠&lt;sup&gt;3&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt; GNU Project, &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html&quot;&gt;“What is Free Software?”&lt;/a&gt; (The Free Software Definition). The same precondition is also listed for Freedom 3.&lt;/span&gt;&lt;/span&gt; If anyone can recover readable code from a binary, in any language of their choosing, that precondition matters a lot less, and with LLMs/AI it’s already close to being met.&lt;/p&gt;&lt;p&gt;My argument is mostly about the open side of Free Software, which is really just &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html#make-changes&quot;&gt;Freedom 1&lt;/a&gt;, the freedom to study and change a program. &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html#run-the-program&quot;&gt;Freedom 0&lt;/a&gt; (run it for any purpose) is a pure permission, as are &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html#redistribute&quot;&gt;Freedoms 2 and 3&lt;/a&gt; (share copies and modified versions); GNU even says Freedom 0 has nothing to do with whether a program is “technically capable of functioning in any given environment”.&lt;/p&gt;&lt;p&gt;GNU lists access to source as a precondition for both Freedom 1 and Freedom 3, but my point about decompilation only changes one of them: it gives you the ability to study and modify a program, not the permission to distribute the result. Which means in both cases, source access is per accidens, and the permission is what’s per se. If anything, I think the heart of the Free Software Movement was always the permission to share (Freedoms 2 and 3), and never really the source.&lt;/p&gt;&lt;p&gt;The obvious objection is that the &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html#four-freedoms&quot;&gt;four freedoms&lt;/a&gt; are permissions, not capabilities: being &lt;em&gt;able&lt;/em&gt; to decompile something doesn’t mean you’re &lt;em&gt;allowed&lt;/em&gt; to. I agree, but I’m not arguing about the &lt;em&gt;permission&lt;/em&gt;. I’m arguing about the technical premise GNU attached to it: “Access to the source code is a precondition for this”. &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html#make-changes&quot;&gt;Freedom 1&lt;/a&gt; is really two claims bundled together: that you need access to the source, and that there shouldn’t be any secrets in the first place. And “cheap” decompilation takes care of the first, because that part was always per accidens. The second is the actual moral claim, and that’s the one I actually disagree with.&lt;/p&gt;&lt;p&gt;To be clear, I’m not claiming decompiled code is as good as the original source. The GPL even defines source as “the preferred form of the work for making modifications to it”,⁠&lt;sup&gt;4&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;4&lt;/span&gt; &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GNU General Public License, version 3&lt;/a&gt;, section 1, “Source Code”. GPLv2 uses the same wording in section 3.&lt;/span&gt;&lt;span&gt;&lt;span&gt;5&lt;/span&gt; Except when you want it in a different language, or the original source wasn’t readable to begin with. Most open source code is hard to read, so even with the original source, you’re still doing your own decompilation, from text to text.&lt;/span&gt;&lt;/span&gt; and the original is virtually always preferred over a decompilation.⁠&lt;sup&gt;5&lt;/sup&gt; But a preference is not a precondition. A precondition is something you can’t do without, and the lack of source never strictly prevented anything; it just made it expensive. People were decompiling entire programs by hand long before LLMs: &lt;a href=&quot;https://github.com/n64decomp/sm64&quot;&gt;Super Mario 64 was decompiled&lt;/a&gt; by hand back into C that compiles to a byte-identical ROM, which is what then made the native PC ports possible; what LLMs/AI change is the cost of this process. Even if the original source has extra information (e.g. comments and names), decompiling with tools like &lt;a href=&quot;https://ghidra-sre.org/&quot;&gt;Ghidra&lt;/a&gt; + LLMs has made the whole process a heck of a lot simpler (for personal use). It’s still harder and messier than having the original source, but it’s possible, which makes source access a convenience rather than a requirement.&lt;/p&gt;&lt;p&gt;And “preferred” is already a matter of degree. Original source, decompiled code, disassembly, and the raw binary are all points on the same gradient. Some things (build scripts, or code behind &lt;code&gt;#ifdef&lt;/code&gt;s for other platforms) aren’t in the binary at all, so you’d have to recreate them rather than read them, but that’s a difference in effort. And if decompilation makes auditing possible without the source, then the source itself isn’t doing the essential work.&lt;/p&gt;&lt;h2&gt;Source Was Never a Guarantee&lt;/h2&gt;&lt;p&gt;Even with the source, you could never really know what was running on a remote server. And even locally, Thompson’s “Reflections on Trusting Trust”⁠&lt;sup&gt;6&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;6&lt;/span&gt; Ken Thompson, &lt;a href=&quot;http://doi.acm.org/10.1145/358198.358210&quot;&gt;“Reflections on Trusting Trust”&lt;/a&gt;, &lt;em&gt;Communications of the ACM&lt;/em&gt; 27(8), August 1984, pp. 761–763. Originally his Turing Award lecture.&lt;/span&gt;&lt;/span&gt; showed you can’t fully trust code you compiled yourself.&lt;/p&gt;&lt;p&gt;The FSF knows both of these: the AGPL exists for the server case⁠&lt;sup&gt;7&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;7&lt;/span&gt; &lt;a href=&quot;https://www.gnu.org/licenses/agpl-3.0.html&quot;&gt;GNU Affero General Public License&lt;/a&gt;, which requires offering the source to users who interact with the software over a network.&lt;/span&gt;&lt;span&gt;&lt;span&gt;8&lt;/span&gt; Google’s &lt;a href=&quot;https://opensource.google/documentation/reference/using/agpl-policy&quot;&gt;AGPL Policy&lt;/a&gt;: code licensed under the AGPL “MUST NOT be used at Google”. Its reading of the AGPL is disputed as the AGPL treats network use as distribution but it doesn’t make the rest of a service a derivative work. Either way, the ban is the point as companies avoid it regardless.&lt;/span&gt;&lt;span&gt;&lt;span&gt;9&lt;/span&gt; David A. Wheeler, &lt;a href=&quot;https://dwheeler.com/trusting-trust/&quot;&gt;“Fully Countering Trusting Trust through Diverse Double-Compiling”&lt;/a&gt;, PhD dissertation, George Mason University, 2009. See also &lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;Reproducible Builds&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt; (though few projects use it, and many companies refuse to touch AGPL code at all; Google bans it outright⁠&lt;sup&gt;8&lt;/sup&gt;), and from what I’ve discussed with others, the answers to Thompson are reproducible builds and diverse double-compiling,⁠&lt;sup&gt;9&lt;/sup&gt; both of which need the source. It does kind of make source necessary for those “solutions”, but they are not sufficient, and very few people actually run them; in practice you’re still trusting someone else’s build. And even in those cases, you still need to trust the bootstrapping stage. There is always a place where you just have to “trust”. And sadly, that means source alone can’t be the guarantee; at best, it’s a mere convenience.&lt;/p&gt;&lt;p&gt;The FSF would say source isn’t about trust at all but about control: without it, the program controls the user. But control is a gradient too, for the same reason trust is. Source, reproducible builds, inspecting the binary, decompiling it: none of these is a guarantee, and each gives you some control over what runs on your machine. The FSF draws a categorical line at one point on that gradient, and my question is why that point?—especially now that the other points keep getting cheaper. Yes, the strongest checks need the source, which makes it the best point on the gradient, but still only a point on it.&lt;/p&gt;&lt;h2&gt;Open Source Is Not a Business Model&lt;/h2&gt;&lt;p&gt;If the technical case for source access is mostly per accidens, the pragmatic case has to carry the weight, and pragmatically, open source has a funding problem.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.catb.org/~esr/&quot;&gt;Eric S. Raymond&lt;/a&gt;, who wrote down much of the original “theory” of &lt;em&gt;open source&lt;/em&gt;,⁠&lt;sup&gt;10&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;10&lt;/span&gt; Eric S. Raymond, &lt;a href=&quot;http://www.catb.org/~esr/writings/cathedral-bazaar/&quot;&gt;&lt;em&gt;The Cathedral and the Bazaar&lt;/em&gt;&lt;/a&gt; (O’Reilly, 1999).&lt;/span&gt;&lt;span&gt;&lt;span&gt;11&lt;/span&gt; &lt;a href=&quot;https://heartbleed.com/&quot;&gt;“The Heartbleed Bug”&lt;/a&gt;. It shipped in OpenSSL 1.0.1 in March 2012 and was disclosed in April 2014.&lt;/span&gt;&lt;/span&gt; in my opinion made an engineering argument rather than a moral one: “given enough eyeballs, all bugs are shallow”. In a way, that’s the main distinction between open source and Free Software. But more eyeballs only make bugs more likely to be found, not certain to be: Heartbleed sat in OpenSSL, one of the most widely used libraries around, for about two years before anyone noticed.⁠&lt;sup&gt;11&lt;/sup&gt; And not to mention, eyeballs aren’t free. Reliability and reusability do not come from merely having source availability; they come from people being paid to maintain and improve the software—an actual incentive. Unfortunately, that is not the &lt;em&gt;reality&lt;/em&gt; of open source.&lt;/p&gt;&lt;p&gt;To be clear, the distinction I’m drawing between Free and &lt;strong&gt;open&lt;/strong&gt; is about motivations and business logic, not licences. The licences mostly overlap, and even GNU says “nearly all open source software is free software”.⁠&lt;sup&gt;12&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;12&lt;/span&gt; GNU Project, &lt;a href=&quot;https://www.gnu.org/philosophy/open-source-misses-the-point.html&quot;&gt;“Why Open Source Misses the Point of Free Software”&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Personally, I think &lt;strong&gt;open&lt;/strong&gt; source is antithetical to “selling software” as a business. Most open source projects can’t really make money from the software itself, so in practice they’re effectively charities. &lt;strong&gt;Open&lt;/strong&gt; source was never “free as in beer” or even “free as in freedom”. It has always been “free as in puppy”: free to get, but the maintenance cost falls on the users as well as the people who made it.⁠&lt;sup&gt;13&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;13&lt;/span&gt; The origin of the phrase is disputed. From what I can tell, it has been attributed to Sun’s Scott McNealy, and Nadia Eghbal’s &lt;em&gt;Working in Public: The Making and Maintenance of Open Source Software&lt;/em&gt; (Stripe Press, 2020) quotes Bootstrap co-creator Jacob Thornton using it. So I have no idea of the actual origin.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;For context, I’ve run multiple open source projects for over a decade, the largest being the &lt;a href=&quot;https://odin-lang.org/&quot;&gt;Odin&lt;/a&gt; compiler. However, I’d never license any of them under the GPL or want to run anything under it. If I want something open, I want it permissive, not viral. Both the Odin compiler and its core library are under the &lt;a href=&quot;https://zlib.net/zlib_license.html&quot;&gt;zlib licence&lt;/a&gt;, which is effectively one step above public domain.⁠&lt;sup&gt;14&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;14&lt;/span&gt; Public domain isn’t legally recognized everywhere, so zlib is about as close as you can get, as well as a few other similar licences.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Odin itself is free precisely because you can’t really sell a compiler anymore: the expected price of a compiler nowadays is zero. Even Intel gave up and made its compilers free. The compilers you can still pay for either have decades of precedent behind them, and thus the inertia (e.g. &lt;a href=&quot;https://www.iar.com/&quot;&gt;IAR&lt;/a&gt; and &lt;a href=&quot;https://www.ghs.com/&quot;&gt;Green Hills&lt;/a&gt; in embedded, or &lt;a href=&quot;https://www.mathworks.com/products/matlab.html&quot;&gt;Matlab&lt;/a&gt; and &lt;a href=&quot;https://www.wolfram.com/mathematica/&quot;&gt;Mathematica&lt;/a&gt; in the sciences), or they aren’t really sold as compilers at all but as entire suites (IDE, debugger, profiler, certification, support), which do far more than a mere language and its core library. And I’d sell Odin if I could, because profit is what pays for making it better. Making a living is not a vice.&lt;/p&gt;&lt;p&gt;And if the authors have no funding, what incentive do they have to keep improving it, the way any business would, other than the kindness of their hearts? To be clear, this isn’t a criticism of permissive licences (I am a user of them), rather neither permissive nor copyleft licensing is a business model in itself.&lt;/p&gt;&lt;p&gt;Most of the open source projects I’ve dealt with aren’t actually good in the slightest, because the people developing them have had no incentive to make them better.⁠&lt;sup&gt;15&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;15&lt;/span&gt; Nadia Eghbal, &lt;a href=&quot;https://www.fordfoundation.org/work/learning/research-reports/roads-and-bridges-the-unseen-labor-behind-our-digital-infrastructure/&quot;&gt;&lt;em&gt;Roads and Bridges: The Unseen Labor Behind Our Digital Infrastructure&lt;/em&gt;&lt;/a&gt; (Ford Foundation, 2016), which covers underfunded projects like OpenSSL and the Heartbleed bug.&lt;/span&gt;&lt;span&gt;&lt;span&gt;16&lt;/span&gt; The &lt;a href=&quot;https://fund.blender.org/&quot;&gt;Blender Development Fund&lt;/a&gt;. At the time of writing, around €280,000 a month from roughly 7,600 individuals and 46 corporate members.&lt;/span&gt;&lt;span&gt;&lt;span&gt;17&lt;/span&gt; Adam Smith, &lt;a href=&quot;https://www.gutenberg.org/ebooks/3300&quot;&gt;&lt;em&gt;The Wealth of Nations&lt;/em&gt;&lt;/a&gt; (1776), on self-interest rather than benevolence.&lt;/span&gt;&lt;span&gt;&lt;span&gt;18&lt;/span&gt; F. A. Hayek, &lt;a href=&quot;https://www.econlib.org/library/Essays/hykKnw.html&quot;&gt;“The Use of Knowledge in Society”&lt;/a&gt;, &lt;em&gt;American Economic Review&lt;/em&gt;, 1945, on prices as signals.&lt;/span&gt;&lt;span&gt;&lt;span&gt;19&lt;/span&gt; Thomas Sowell, &lt;em&gt;Knowledge and Decisions&lt;/em&gt; (1980), an accessible treatment of prices as information.&lt;/span&gt;&lt;/span&gt; They’re effectively charities, and even the popular ones are. Blender is one of the most popular open source projects around, and it’s paid for by donations to the Blender Development Fund from thousands of individuals and dozens of companies, such as NVIDIA and Netflix,⁠&lt;sup&gt;16&lt;/sup&gt; and at the end of the day, that’s still charity even if it’s just at scale. A profit motive isn’t a bad thing at all;⁠&lt;sup&gt;17&lt;/sup&gt; prices are just a signal mechanism, and they’re what allow for rational calculation in the first place;⁠&lt;sup&gt;18&lt;/sup&gt;&lt;sup&gt;, 19&lt;/sup&gt; without those signals, you’re kind of just screwed.&lt;/p&gt;&lt;p&gt;The usual objection is that money corrupts priorities: managers reward adding features, never removing them, and so commercial software bloats. That does happen, but it’s an organisational problem, not a money problem. It’s just Conway’s law: a system’s design ends up copying the communication structure of the organisation that built it.⁠&lt;sup&gt;20&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt; Melvin E. Conway, &lt;a href=&quot;http://www.melconway.com/Home/Committees_Paper.html&quot;&gt;“How Do Committees Invent?”&lt;/a&gt;, &lt;em&gt;Datamation&lt;/em&gt;, April 1968.&lt;/span&gt;&lt;span&gt;&lt;span&gt;21&lt;/span&gt; Casey Muratori, &lt;a href=&quot;https://www.youtube.com/watch?v=5IUj1EZwpJY&quot;&gt;“The Only Unbreakable Law”&lt;/a&gt;, a talk on Conway’s law and why it can’t be avoided.&lt;/span&gt;&lt;/span&gt;&lt;sup&gt;, 21&lt;/sup&gt; And open source isn’t immune to any of this either. A feature is far easier to get merged than a removal. And (unfortunately) most large open source projects are funded by the same huge corporations, with the same performance reviews. At least when customers can leave (assuming an alternative exists), bloat costs you something.&lt;/p&gt;&lt;p&gt;Those same corporations are behind most of the big successful (non-copyleft) &lt;strong&gt;open&lt;/strong&gt; source projects, done in “goodwill” because they can afford to be “kind”. And I’d easily argue that a lot of the time it isn’t kindness at all, but a way to undercut commercial competition and dominate a market, simply because they can afford to give it away.&lt;/p&gt;&lt;p&gt;And the companies that did try to build a business directly on open source show it best. When the “open source companies” of the last decade (MongoDB, Elastic, HashiCorp, and Redis) needed revenue, they all moved to source-available licences, mostly to stop cloud providers selling their own work back to their customers.⁠&lt;sup&gt;22&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;22&lt;/span&gt; &lt;a href=&quot;https://www.mongodb.com/press/mongodb-issues-new-server-side-public-license-for-mongodb-community-server&quot;&gt;MongoDB&lt;/a&gt; moved from the AGPL to the SSPL in 2018, &lt;a href=&quot;https://www.elastic.co/blog/licensing-change&quot;&gt;Elastic&lt;/a&gt; from Apache 2.0 to the SSPL and Elastic License in 2021, &lt;a href=&quot;https://www.hashicorp.com/en/blog/hashicorp-adopts-business-source-license&quot;&gt;HashiCorp&lt;/a&gt; from the MPL to the BSL in 2023, and &lt;a href=&quot;https://redis.io/blog/redis-adopts-dual-source-available-licensing/&quot;&gt;Redis&lt;/a&gt; from BSD to the RSAL and SSPL in 2024. &lt;a href=&quot;https://www.elastic.co/blog/elasticsearch-is-open-source-again&quot;&gt;Elastic&lt;/a&gt; and &lt;a href=&quot;https://redis.io/blog/agplv3/&quot;&gt;Redis&lt;/a&gt; later added the AGPL back as an option.&lt;/span&gt;&lt;/span&gt; Open source was the marketing, not the business model, because it can’t sustain one.&lt;/p&gt;&lt;h2&gt;The Exceptions That Prove the Rule&lt;/h2&gt;&lt;p&gt;Linux is effectively the canonical exception, since much of it is written by developers paid by companies that depend on it. But I’d argue that’s because of the sheer scale of building a kernel/OS, not anything inherent to the GPL. The usual counter I have seen is that the GPL is precisely &lt;em&gt;why&lt;/em&gt; those companies cooperate: none of them can take the shared work private, meaning contributing is safe. There’s some truth to that, but permissively licensed projects like LLVM⁠&lt;sup&gt;23&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;23&lt;/span&gt; As people who know me know, I have no love for LLVM whatsoever, and it has been the bane of my existence for over a decade now.&lt;/span&gt;&lt;/span&gt; get the same kind of corporate cooperation without it, so the GPL isn’t necessary for it.&lt;/p&gt;&lt;p&gt;And even Linux doesn’t follow the FSF’s intent. Linus kept it on GPLv2 because it only asks for “tit-for-tat”, which he called “totally independent of any moral judgement”,⁠&lt;sup&gt;24&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt; Linus Torvalds, &lt;a href=&quot;https://lkml.iu.edu/hypermail/linux/kernel/0609.3/0248.html&quot;&gt;“An Ode to GPLv2”&lt;/a&gt;, Linux kernel mailing list, September 2006.&lt;/span&gt;&lt;/span&gt; and he objected to GPLv3’s anti-Tivoization clause, the requirement to let users run modified versions on the device itself. That’s why vendors can still lock down the devices Linux ships in. It’s an engineering argument for sharing code, not the FSF’s moral one.&lt;/p&gt;&lt;p&gt;The same pattern shows up in the other big GPL successes: GCC succeeded through scale too, and WordPress makes its money through other means.⁠&lt;sup&gt;25&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;25&lt;/span&gt; WordPress makes its money from everything around the code: Automattic sells hosting (WordPress.com and enterprise hosting) and WooCommerce extensions, and the premium plugin and theme market really sells updates and support.&lt;/span&gt;&lt;/span&gt; GCC also helped make everyone expect a compiler to cost nothing, which effectively killed an entire software business model for many people. Its main competitors, Clang and MSVC, are backed by Apple and Microsoft, who can afford to give them away.&lt;/p&gt;&lt;p&gt;MySQL, Qt, and wolfSSL are the interesting cases, since they make money through dual licensing: selling a proprietary licence to anyone who doesn’t want the GPL’s terms. These are business models which seem to depend on copyleft, but look at what’s actually being sold: an exemption from the GPL. Nobody pays to escape a zlib licence. The GPL is the “stick” and the non-free licence is the product. And even that didn’t keep MySQL independent: Sun bought it in 2008, and it came to Oracle along with Sun in 2010. Oracle makes its money through other means, not least its own proprietary database. In other words, the GPL’s successes are &lt;em&gt;per accidens&lt;/em&gt; as well, not &lt;em&gt;per se&lt;/em&gt;.&lt;/p&gt;&lt;h2&gt;Copyleft Needs Copyright&lt;/h2&gt;&lt;p&gt;Red Hat is one of the rare companies to build a sustainable business on GPL software, mainly because of when they started and because what customers really pay for is the support, certification, and enterprise trust, not the code. And even then, RHEL isn’t really &lt;strong&gt;open&lt;/strong&gt;. It’s closer to source-available on purchase, since they limit the source to paying customers and use their subscription terms to discourage redistribution.⁠&lt;sup&gt;26&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;26&lt;/span&gt; Mike McGrath, &lt;a href=&quot;https://www.redhat.com/en/blog/furthering-evolution-centos-stream&quot;&gt;“Furthering the evolution of CentOS Stream”&lt;/a&gt;, Red Hat blog, June 2023. It made CentOS Stream the sole public source for RHEL-related code, with RHEL sources available to customers under their subscription agreements.&lt;/span&gt;&lt;span&gt;&lt;span&gt;27&lt;/span&gt; &lt;a href=&quot;https://www.theregister.com/2023/06/23/red_hat_centos_move/&quot;&gt;The Register’s coverage&lt;/a&gt; of Red Hat’s source change, June 2023.&lt;/span&gt;&lt;/span&gt;&lt;sup&gt;, 27&lt;/sup&gt; I’d argue this is effectively a loophole around the GPL, since the GPL lets anyone who receives the source redistribute it, which normally makes selling it hard to sustain. Whether those terms actually comply with the GPL is disputed. Like MySQL, Red Hat sells something the GPL leaves room for, in their case support, certification, and controlled access to the source; neither generalizes into a business model for software as a whole.&lt;/p&gt;&lt;p&gt;And in many ways, it also shows the movement doesn’t really &lt;em&gt;subvert&lt;/em&gt; IP. In GNU’s own words, copyleft “uses copyright law, but flips it over to serve the opposite of its usual purpose”.⁠&lt;sup&gt;28&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;28&lt;/span&gt; Richard Stallman, &lt;a href=&quot;https://www.gnu.org/gnu/thegnuproject.html&quot;&gt;“The GNU Project”&lt;/a&gt;, “Copyleft and the GNU GPL”. See also GNU’s &lt;a href=&quot;https://www.gnu.org/copyleft/copyleft.html&quot;&gt;“What is Copyleft?”&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt; But RHEL shows how easily that flip is undone. The GPL only works because copyright exists (as do permissive licences, of course), and Red Hat simply layers contracts on top to stop people redistributing source they legally received. So copyleft doesn’t escape IP; it depends on it, and loses to the very same legal tools.&lt;/p&gt;&lt;p&gt;Many (not all) Free Software advocates are anti-IP, and would happily see copyright, and copyleft with it, abolished. But without copyright, &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html#redistribute&quot;&gt;Freedoms 2 and 3&lt;/a&gt; are only worth whatever you can get your hands on, because nothing forces anyone to hand over the source. Businesses would fall back on trade secrets, contracts, and DRM, which is exactly what I expect them to do anyway. And that’s not a rare fallback: the vast majority of businesses already work this way. A recipe, a manufacturing process, a customer list, or just knowing how to do something others don’t, is what most businesses are built on, not copyright. Software is no different.&lt;/p&gt;&lt;p&gt;To be clear, I’m not advocating for abolishing IP. Parts of it are flawed (&lt;a href=&quot;https://caseymuratori.com/blog_0027&quot;&gt;software patents&lt;/a&gt; especially), but it exists for a reason: it protects the work and investment that went into making something—so that it’s worth making in the first place. Take it away and that protection doesn’t disappear; it just moves into secrecy, contracts, and DRM.&lt;/p&gt;&lt;h2&gt;What I Expect to Happen&lt;/h2&gt;&lt;p&gt;If decompilation keeps getting easier, I do expect the industry to respond in a few ways:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Hardware DRM that protects binaries and process memory from even being read.&lt;/li&gt;
&lt;li&gt;More use of kernel-level DRM, similar to anti-cheat software.&lt;/li&gt;
&lt;li&gt;A legal hellscape where everyone is suing everyone all the time.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Unfortunately, I expect all of them to happen. I am very conflicted about this, because it’s very similar to the idea behind signed binaries and TPMs, which end up becoming “we decide what software will run on your machine”. I know it doesn’t have to be like that at all, but it could be.&lt;/p&gt;&lt;p&gt;Some will say this proves the FSF right all along, since this is exactly the lockdown they’ve warned about.⁠&lt;sup&gt;29&lt;/sup&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;29&lt;/span&gt; Richard Stallman, &lt;a href=&quot;https://www.gnu.org/philosophy/right-to-read.html&quot;&gt;“The Right to Read”&lt;/a&gt;, &lt;em&gt;Communications of the ACM&lt;/em&gt;, February 1997.&lt;/span&gt;&lt;span&gt;&lt;span&gt;30&lt;/span&gt; Richard Stallman, &lt;a href=&quot;https://www.gnu.org/philosophy/can-you-trust&quot;&gt;“Can You Trust Your Computer?”&lt;/a&gt; (2002), on “treacherous computing”.&lt;/span&gt;&lt;/span&gt;&lt;sup&gt;, 30&lt;/sup&gt; But predicting an outcome isn’t the same as being right about its cause. The FSF movement is effectively anti-trade-secret to begin with. In their view, if you distribute software in any form, even compiled and obfuscated, the source should be shared with the world. Their reasoning is about control: without the source, the user doesn’t control the program, the program controls the user. But “trivial” decompilation now gives you most of that control without the source, so what’s left of the demand is simply that a secret must not stay a secret. And a lot of businesses, especially small ones, exist precisely because of their trade secrets, so why the heck should they ever release any of that?&lt;/p&gt;&lt;p&gt;Compiled binaries used to be a cheap form of protection. If decompilation removes that, companies won’t go the FSF route. They’ll reach for the expensive forms instead: hardware, kernel-level DRM, and lawyers, and the FSF’s dream wouldn’t be any better. If in this “future” all software had to be free, most of it would be the charity I described above, with little incentive to improve. Either way, it would be a dark age for software.&lt;/p&gt;&lt;p&gt;But there is another option, and it isn’t a new idea: stay closed, but make the closed version worth paying for. Piracy has always been a problem, and decompilation only makes it easier. Yet Steam and Netflix are both closed source, and they made piracy matter a lot less not by opening up, nor by locking things down harder, but by being more convenient than the pirates. As Gabe Newell put it:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Piracy is almost always a service problem and not a pricing problem. &lt;/p&gt;&lt;footer&gt;Gabe Newell, interviewed by &lt;em&gt;The Cambridge Student&lt;/em&gt;, November 2011, as reported by &lt;a href=&quot;https://mcvuk.com/business-news/consoles/newell-piracy-is-a-non-issue-for-valve/&quot;&gt;MCV&lt;/a&gt;.&lt;/footer&gt;
&lt;/blockquote&gt;&lt;p&gt;Neither Steam nor Netflix would ever open up the software their business runs on (the Steam client and store, or Netflix’s apps and recommendations), even though both happily open source the parts that aren’t their business. That software &lt;em&gt;is&lt;/em&gt; the business; the service is what makes paying for it easier than pirating it.&lt;/p&gt;&lt;p&gt;And yes, this means the ability to decompile is contingent too: it lasts only as long as hardware and law allow it, but that’s my point. None of the technical conditions, source, or binary, were ever per se. The real question is who draws the line: hardware vendors, the FSF’s demand that all source be shared, or ordinary markets and contracts. Personally I usually prefer to pick the last one. Paid, closed software with clear legal terms protects a company’s work without locking down your machine, and it gives developers a price signal and a reason/incentive to keep improving the software.&lt;/p&gt;&lt;p&gt;The FSF route turns software into a form of forced-charity, and the hardware vendors’ route turns your computer into someone else’s. Paid closed software with clear legal terms is the least bad option, and we should stop treating it as if it was the villain.&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;LLMs have made decompilation a lot simpler. I’m not saying that makes Free Software necessarily wrong, but it does show which parts of it were per accidens. The technical premise behind GNU’s Freedom 1 (that you need the source to study or change a program) was always about cost and never a principle.&lt;/p&gt;&lt;p&gt;What remains as &lt;em&gt;per se&lt;/em&gt; are Freedoms 2 and 3 (the permission to share copies and modified versions) and the moral claim that software shouldn’t have secrets, but neither of these points is technical. The first is a question of copyright, which copyleft depends on as much as anything proprietary does; the second is a claim against trade secrets, which is what most businesses are built on. I don’t think either aspect holds up in the reality of business.&lt;/p&gt;&lt;p&gt;Open source was never a business model in the first place. If decompilation makes binaries a weaker protection, the answer isn’t to give everything away, but to make the closed thing worth paying for, or keep it on a server where it never leaves your hands.&lt;/p&gt;&lt;p&gt;The “essential” arguments for OSS/FOSS/Free-Software might be a lot smaller than even their advocates realized.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Why is it so expensive to send an email?</title>
<link>https://evancz.dev/why-is-it-so-expensive-to-send-an-email</link>
<guid isPermaLink="false">F6eqfjw1jS0R1an3Sul_xsBcIg-c5cSDGtyr2A==</guid>
<pubDate>Mon, 26 Oct 2026 17:39:11 +0000</pubDate>
<description>Sending an email is essentially the same as making an HTTPS request, so how can companies charge $15 to send 1000 emails?</description>
<content:encoded>&lt;h1&gt;Why is it so expensive to send an email?&lt;/h1&gt;&lt;p&gt;Sending an email is essentially the same as making an HTTPS request. You open a TCP connection to port 25, you do a little SSL handshake, and you send some data through. Most personal computers out there can easily do this thousands of times per second, so &lt;strong&gt;how can companies charge $15 to send 1000 emails?!&lt;/strong&gt; Why do I need some 3rd party company involved at all?! I used to work at Google specifically on GMail, and nothing from my little corner of the product on the “tabbed inbox” team led me to a clear answer...&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Unfortunately for me, I was determined to figure it out for myself!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;I mostly program with Haskell, and I call C code as necessary for things like OpenSSL and SQLite. I already had a setup for making HTTPS requests from my Haskell code with OpenSSL. I had code for working with HTTP 1.1 messages. How hard could it be to adapt this to email? To my surprise, it turns out that the actual “sending” part is not that hard. The real problem was ultimately out of my hands...&lt;/p&gt;&lt;h2&gt;Simple Mail Transfer Protocol&lt;/h2&gt;&lt;p&gt;Just like the original plaintext Hypertext Transfer Protocol (HTTP 1.1), there is a correspondingly goofy plaintext protocol for sending emails called Simple Mail Transfer Protocol (SMTP). The original version of the protocol involves sending a bunch of messages back and forth and back and forth between the sender and receiver. It looks kind of like a little conversation. Here is an example where I start my messages with keywords like &lt;code&gt;HELO&lt;/code&gt; and &lt;code&gt;MAIL FROM&lt;/code&gt; and the receiver starts her messages with status codes like &lt;code&gt;220&lt;/code&gt; and &lt;code&gt;250&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(Evan opens the TCP connection)
220 mail.example.com
HELO evancz.dev
250 Hello evancz.dev, I am glad to meet you
MAIL FROM:&amp;lt;devnull@evancz.dev&amp;gt;
250 OK
RCPT TO:&amp;lt;alice@example.com&amp;gt;
250 OK
DATA
354 End data with &amp;lt;CR&amp;gt;&amp;lt;LF&amp;gt;.&amp;lt;CR&amp;gt;&amp;lt;LF&amp;gt;
From: &amp;quot;Evan from Elm&amp;quot; &amp;lt;devnull@evancz.dev&amp;gt;
To: &amp;quot;Alice from Cryptography&amp;quot; &amp;lt;alice@example.com&amp;gt;
Date: Wed, 21 Oct 1981 8:33:40 +0100
Subject: Big Fan!

Hello Alice from Cryptography,

I loved your collaboration with Rivest, Shamir, and Adleman
in 1977. I have been eagerly awaiting the invention of email,
so that I could express my admiration through this plaintext
transfer protocol!

Best,
Evan from Elm
.
250 OK: queued as 12345
QUIT
221 Bye
(Alice closes the connection)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So to send a single email, you originally had to do SEVEN roundtrips! And TLS did not exist at that time, so you did not even get any encryption after all those roundtrips!&lt;/p&gt;&lt;p&gt;That said, it is not that hard to send and receive a bunch of goofy plaintext, so I set it up and sent an email to myself. It worked! But... it showed up in spam.&lt;/p&gt;&lt;h2&gt;Wait, who sent that message?!&lt;/h2&gt;&lt;p&gt;The original protocol has a very serious flaw. &lt;strong&gt;How does &lt;code&gt;mail.example.com&lt;/code&gt; know that I am &lt;code&gt;devnull@evancz.dev&lt;/code&gt; and not an imposter?&lt;/strong&gt; The original protocol lets you just claim whatever sender you want, so anybody in the whole world could easily spoof the domain and sender.&lt;/p&gt;&lt;p&gt;So these days you need to add some &lt;code&gt;TXT&lt;/code&gt; records to the DNS for your domain. This way the receiver can go look up some public encryption keys for &lt;code&gt;evancz.dev&lt;/code&gt; and confirm that whoever sent the email at least has access to the private key.&lt;/p&gt;&lt;p&gt;At this point I started wondering, wait, how do you prevent someone from spoofing the DNS records? Like what if &lt;a href=&quot;https://www.propublica.org/article/nsa-spying-relies-on-atts-extreme-willingness-to-help&quot;&gt;the NSA and AT&amp;amp;T were collaborating&lt;/a&gt; or what if &lt;a href=&quot;https://www.washingtonpost.com/graphics/2020/world/national-security/cia-crypto-encryption-machines-espionage/&quot;&gt;the CIA had a history of creating companies like Crypto AG to backdoor cryptographic systems from the very beginning&lt;/a&gt;? It seems like a problem... But hey, I just want to send an email and it looks like all you have to do is set up these DNS records.&lt;/p&gt;&lt;p&gt;So I set up a private key, added some DNS records, ran my emails through some OpenSSL functions, and I started sending emails again!&lt;/p&gt;&lt;p&gt;Now my emails were showing up in my inbox in GMail! Heck yeah! The technical details were not hard, only sort of annoying to figure out. So why does it cost $15 to send 1000 emails?!&lt;/p&gt;&lt;p&gt;When the database backend for Elm went into private alpha, I decided to try sending the transactional emails myself. Just some Haskell and C code making TCP connections! My thinking was that if I ever set up a hosting service to support Elm development, maybe it would be cool to handle emails as well. The whole goal of Elm is to filter out all the irrelevant details and let the programmer focus on the actually meaningful parts, so it seemed like there might be something there!&lt;/p&gt;&lt;p&gt;Okay, but then I noticed that the emails were &lt;em&gt;only&lt;/em&gt; showing up in GMail. People who used Microsoft Outlook were not even seeing them in spam...&lt;/p&gt;&lt;h2&gt;Old and Goofy Spam Filters&lt;/h2&gt;&lt;p&gt;Once someone adds the DNS records to verify their identity, it is still possible for them to just start blasting out spam. I was not sending spam, but I was now interacting with a baroque mosaic of spam detection filters that sometimes work in funny ways.&lt;/p&gt;&lt;p&gt;Each email inbox provider has different algorithms for determining “the reputation” of the sender. Some inboxes are able to mostly assess the reputation of the sender’s domain. “Are the emails from this domain good?” Other inboxes seem to care more about the particular IP address. “If one domain on a given IP address is bad, maybe other domains on that IP address are bad too!” Other inboxes seem to really care about the IP address &lt;strong&gt;block&lt;/strong&gt;. “If someone is sending spam from &lt;code&gt;100.0.0.0&lt;/code&gt;, then maybe the whole &lt;code&gt;100.0.*.*&lt;/code&gt; block is a problem!”&lt;/p&gt;&lt;p&gt;So it is possible that an inbox like Microsoft Outlook really cares about IP address &lt;strong&gt;blocks&lt;/strong&gt;. Maybe they do not have a very fine-grained way of assessing individual IP addresses, or maybe this is just a good for a filter for “big business” users. I have no idea, and I have no special inside knowledge. The point is that this appears to be true for some of the many many inbox services out there. Even if it is not true this month, it may be true next month as the developers at Yahoo Mail, Zoho Mail, Proton Mail, etc. etc. adapt to whatever spammers are getting up to recently.&lt;/p&gt;&lt;p&gt;I host my servers with a smaller cloud provider, so I have access to whichever IP address blocks they offer. I can get a fixed IP address and treat it nicely, but again, some email inboxes seem to really care about the entire IP address &lt;strong&gt;block&lt;/strong&gt;. That means that if &lt;em&gt;anyone&lt;/em&gt; is sending spam through my cloud services provider, my whole IP address &lt;strong&gt;block&lt;/strong&gt; may get blacklisted.&lt;/p&gt;&lt;p&gt;So finally we come to the reason why sending emails costs so much.&lt;/p&gt;&lt;h2&gt;My Personal Conclusion&lt;/h2&gt;&lt;p&gt;Actually setting up the code to send emails is a relatively doable one-time thing. From a technical perspective, it is essentially the same as sending an HTTPS request.&lt;/p&gt;&lt;p&gt;But to deliver to all different email addresses, you need to be trusted by inbox providers with the oldest and goofiest spam filters. Since some inboxes seem to really care about IP address blocks, &lt;strong&gt;this means you probably need to get your own IP address block.&lt;/strong&gt; And from there, you need to send a pretty high volume of emails through it per day.&lt;/p&gt;&lt;p&gt;My emails went through to certain inbox providers just fine, so it must be &lt;em&gt;possible&lt;/em&gt; for them to avoid heavily relying on IP address block blacklists. The particular feature I worked on at Google was the “tagged inbox” where emails get sorted into primary, promotions, social, updates, and forums. I never really talked to the spam people down the hall, but maybe things like the human categorization from tagged inbox helps them get a better signal on domain names such that they can rely less on the IP address block blacklists? I honestly have no idea. It was a big office, and the “more exciting” gossip mostly came from the other side of the building where the Google+ people were developing a Facebook killer in the era of “social search”.&lt;/p&gt;&lt;p&gt;In any case, this is where my personal exploration ended. Hopefully it helps readers who have never tried to send emails from scratch, and I will be curious to hear from the collective “spam people down the hall” if there is anything I got wrong! (I am sure there is!)&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Drawing Boxes vs. Shading Them In - BiteofanApple</title>
<link>https://brianschrader.com/archive/drawing-lines-vs-shading-in/</link>
<guid isPermaLink="false">l2YOiJWYVf0FPL7--pcVk-5puRJP2yI06_A71Q==</guid>
<pubDate>Mon, 26 Oct 2026 17:27:14 +0000</pubDate>
<description>A look at what humans are really doing when we invent, build, or discover new things.</description>
<content:encoded>&lt;p&gt;There are two primary kinds of human endeavor: drawing boxes and shading them in. The first defines the boundaries of behavior, culture, and discussion; it draws the boxes. The latter implements those definitions and works within those boundaries. In other words, it shades them in.&lt;/p&gt;&lt;p&gt;I think these two definitions can help us grapple with a lot of the current debate around the role of humans and A.I. going forward. To see how, let&amp;#39;s first explore what I mean by shading in via some historical analogues.&lt;/p&gt;&lt;h2&gt;Shading In&lt;/h2&gt;&lt;p&gt;For simplicity, let&amp;#39;s pick a story most people might be familiar with: classical physics. The broad story goes thus:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;At first no one really knew why or how things moved. Aristotle had some ideas, they weren&amp;#39;t all that useful.&lt;/li&gt;
&lt;li&gt;Then Isaac Newton (and Godfried Liebnitz) discovered calculus and Newton coined his so called &lt;q&gt;Laws of Motion&lt;/q&gt;. Together those two ideas set modern physics, well, into &lt;em&gt;motion&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The next two centuries spawned innovators who built on Newton, abstracted his math, and applied his principles to a huge range of problems.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In this way people like Euler, Lagrange, and Maxwell built on Newton&amp;#39;s ideas, expanding them, formalizing them, and using them to build telegraphs, and rockets, and space probes, and eventually the Internet. This is of course an over-simplification, but let&amp;#39;s go with it.&lt;/p&gt;&lt;p&gt;In this formulation, Newton didn&amp;#39;t simply take another step along the road. He defined the very foundation of a new discipline. After that countless physicists and engineers &lt;q&gt;filled in the gaps&lt;/q&gt; by plugging holes in the theory and applying its principles to the real world. This is where the real advancement happens.&lt;/p&gt;&lt;p&gt;Obviously though, this change didn&amp;#39;t happen immediately. This is because shading in takes time. It&amp;#39;s limited by the knowledge of people in a given place and their ability to find occasion to use a new piece of tech. Of course, as all software devs learn, the actual process of building takes time too.&lt;/p&gt;&lt;div&gt;
  &lt;div&gt;
    &lt;div&gt;
      
    &lt;/div&gt;
    &lt;a href=&quot;https://sendfox.com/brianschrader/&quot;&gt;
      ✉️ Subscribe to the Newsletter!
    &lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In this way, we can see that &lt;em&gt;innovation&lt;/em&gt; broadly defined propagates as a wave from some source. The speed of that wave depends on three factors:&lt;/p&gt;&lt;center&gt;&lt;code&gt;knowledge transmission + application discovery + implementation&lt;/code&gt;&lt;/center&gt;&lt;p&gt;As another example, think of the digital revolution. Once the World Wide Web became available to the public, it took time to build out the physical infrastructure. Then it took time to discover new techniques for building in this new world and find places where these technologies could or should be used. Finally, it took time (and a lot of money) to actually build those things we&amp;#39;d decided were useful.&lt;/p&gt;&lt;div&gt;
  &lt;video&gt;
    
  &lt;/video&gt;
  &lt;center&gt;&lt;small&gt;
    An alternate illustration to &lt;a href=&quot;https://brianschrader.com/archive/lanterns-in-the-void-science-and-discovery/&quot;&gt;the one shown here&lt;/a&gt; that demonstrates the influence of information &lt;q&gt;shading in&lt;/q&gt; a given
    area of thought or realm of knowledge.&lt;br/&gt;Simulation via tools from &lt;a href=&quot;https://falstad.com/ripple/&quot;&gt;Paul Falstad&lt;/a&gt;.
  &lt;/small&gt;&lt;/center&gt;
&lt;/div&gt;&lt;p&gt;Automations of that last step are always good. Assembly lines not only standardized output, they dramatically cut the time it took for cars to go from a drawing to a product in people&amp;#39;s driveways. LLMs for coding and math are basically the same thing.&lt;/p&gt;&lt;p&gt;There has always been a huge demand for software, evidenced by its high cost and near constant growth. The world has continued to find new places to use computers and software to solve our problems and improve our lived reality. The wave of innovation created by the emergence of the personal computer and the World Wide Web has shaded in the boxes drawn by the invention of those technologies. What we&amp;#39;re seeing now is the dramatic speed up of that innovation which is no longer so limited by the speed of implementation.&lt;/p&gt;&lt;p&gt;Much of mathematics (and of all human knowledge discovery) is too a game of shading in the gaps. This shading in happens gradually because &lt;a href=&quot;https://www.youtube.com/watch?v=aXRTczANuIs&quot;&gt;of the nature of causality&lt;/a&gt;. Humans learn and pass on information, which takes time to do. The state of knowledge evolves over time and the gaps between knowledge slowly gets filled in. One could argue, and in fact I would, that there is a huge amount of &lt;em&gt;latent knowledge&lt;/em&gt; sitting in the literature. So much has &lt;em&gt;technically&lt;/em&gt; been discovered already, but no one has put the pieces together yet.&lt;/p&gt;&lt;p&gt;In a world where humans were part of a hive mind this wouldn&amp;#39;t happen. The mathematician &lt;a href=&quot;https://brianschrader.com/archive/drawing-lines-vs-shading-in/[x]&quot;&gt;Kevin Buzzard&lt;/a&gt; said it differently:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;If one human had an understanding of all of modern pure mathematics simultaneously, how much further would they immediately be able to see?&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;We do not know the answer to this question, just as we cannot know what the edge of the universe looks like &lt;a href=&quot;https://www.youtube.com/watch?v=AwwIFcdUFrE&quot;&gt;right now&lt;/a&gt; because it takes time to get there.&lt;/p&gt;&lt;p&gt;In the past this knowledge has taken human effort to find, but the act of shading in the bounds of knowledge is, in some places, now a thing that can be sped up drastically by machines. Software is similar. So much software is needed to run the modern world, but it&amp;#39;s always been limited by the amount of money and human time that could be afforded to a problem. That&amp;#39;s still true, but the budget now goes further than it could before. Slowly we will shade in and write all of the software we need to run the modern world just as we will more quickly begin to understand the nuances and the gaps in our mathematics.&lt;/p&gt;&lt;h2&gt;Drawing Boxes&lt;/h2&gt;&lt;p&gt;The second kind of human endeavor is fundamentally different from the first. We can come to understand it by examining the assumptions that we made above. As I discussed in &lt;a href=&quot;https://brianschrader.com/archive/lanterns-in-the-void-science-and-discovery/&quot;&gt;an earlier post&lt;/a&gt;, in order to fill in a space one must assume it is finite in size. In order to shade in an empty box, you need to draw the box!&lt;/p&gt;&lt;p&gt;This is the kind of thing that a machine learning tool based on human input can never do. Inherently backward looking tech can shade, but it cannot draw the boxes in the first place. It&amp;#39;s a fundamental design flaw and one that cannot be fixed until the machines experience the world as we do. We should be questioning assumptions, defining new terms, sketching out the boxes which define new disciplines. Then we can let the boxes get filled in by our technology.&lt;/p&gt;&lt;p&gt;The labor of humans then is finally free from shading in. Our ability to do so has been dramatically increased and perhaps may even someday be largely automated. The thing is, this is good. There is much work left to do.&lt;/p&gt;&lt;div&gt;
  &lt;video&gt;
    
  &lt;/video&gt;
  &lt;center&gt;&lt;small&gt;
    Video Credit: me
  &lt;/small&gt;&lt;/center&gt;
&lt;/div&gt;&lt;p&gt;As Buzzard said in that same earlier post: &lt;q&gt;mathematics is infinite&lt;/q&gt;. Software is too. So is almost every human endeavor. There is always more to do. Yes it&amp;#39;s different work, but none of us farm by hand anymore, even those few people who enjoyed it. We&amp;#39;ve found new and better things to do: we breed new plants, we do landscaping, we make art, and we invented computers and trains and the internet.&lt;/p&gt;&lt;h2&gt;Zooming Out&lt;/h2&gt;&lt;p&gt;I don&amp;#39;t want this to be the typical &lt;q&gt;technology makes new jobs we haven&amp;#39;t thought of yet&lt;/q&gt; kind of post. I don&amp;#39;t intend that. Software as a discipline is changing. Sadly the hero-myths of the solo dev hacking on a mountaintop are truly dead, but so are the stories those were based on: those of the sage-like pagan hermits who ascended the mountaintop to attain some great truth.&lt;/p&gt;&lt;p&gt;From my own experience I have found that knowledge of code is now secondary to knowledge of paradigms, of data flows, of constraints, of testing, of validation, and of system design. I didn&amp;#39;t shift, I &lt;em&gt;zoomed out&lt;/em&gt;. It&amp;#39;s hard to do, especially because I&amp;#39;ve built my whole career and much of my identity on the old definition of what it meant to be a good software developer, but the times have changed. What&amp;#39;s more &lt;em&gt;it&amp;#39;s better that we can do more now&lt;/em&gt;. It&amp;#39;s better we can learn more things. Our understanding of mathematics will only grow. Our ability to make software that&amp;#39;s tested and full-featured will only increase. Our job is to sketch out the bounds of what we want the world to do, to draw the boxes we want to see filled in.&lt;/p&gt;&lt;p&gt;In the old world, before the computers we know today there were still computers. They were people. They crunched numbers for experienced engineers so they could focus on the bigger picture. In the end, the precise angle of the nose cone isn&amp;#39;t all that important. It&amp;#39;s required, sure, but it&amp;#39;s far more important to zoom out and get the bigger picture: the orbit, its shape, the balance of fuel and weight.&lt;/p&gt;&lt;p&gt;I&amp;#39;m scared, I&amp;#39;ll admit, but I&amp;#39;m also excited to see what happens now that mathematics and software can zoom out another level and focus on new problems.&lt;/p&gt;&lt;p&gt;For years programmers argued about tests: how to write them, what is worthwhile to test and what isn&amp;#39;t. These are concerns you have when test writing costs money, when it takes a lot of time—peak shading in. Now it&amp;#39;s easy to get to 80-90% coverage and it costs basically nothing. Finally, we&amp;#39;re free! No one enjoyed that work. No one wanted to do it. Now, no one has to. We can zoom out and worry about questions we didn&amp;#39;t have the bandwidth to think about before.&lt;/p&gt;&lt;p&gt;In a recent &lt;a href=&quot;https://www.youtube.com/watch?v=LKrwhjOI8Nc&quot;&gt;3Blue1Brown&lt;/a&gt; video, Grant Sanderson touched on a similar idea. He drew the distinction slightly differently: proving theorems vs. theory building. I think this applies far beyond mathematics and software, but I&amp;#39;d expect software development to focus more on erecting guardrails, writing documentation, and verifying results. In other words: it&amp;#39;ll be about theory building (documentation) and verification (proving results). If a discipline can determine how to do those two things, then I&amp;#39;d expect it to quickly become revolutionized. However it&amp;#39;s a very open question &lt;em&gt;if&lt;/em&gt; that is actually possible. What does it mean to &lt;em&gt;theory-build&lt;/em&gt; and &lt;em&gt;verify&lt;/em&gt; the working of a manufacturing process?&lt;/p&gt;&lt;h2&gt;The Words Belong to Us&lt;/h2&gt;&lt;p&gt;I say all this because I think we&amp;#39;re in the middle of a shift in the way humans will participate in the advancement of knowledge. It could be that A.I. models like LLMs will simply improve our ability to search the space of existing knowledge: basically better web search. However we&amp;#39;ve already seen many other emergent use cases, especially in mathematics and sofware, that challenge this idea.&lt;/p&gt;&lt;p&gt;A.I. has the potential to improve every single part of the wave speed formula above, and so dramatically improve our ability to spread novel innovations and discover those latently sitting in our existing whitepaper hoards.&lt;/p&gt;&lt;p&gt;It&amp;#39;s important to remember that these algorithms &lt;a href=&quot;https://brianschrader.com/archive/words-are-a-leaky-abstraction/&quot;&gt;depend on words&lt;/a&gt; as we&amp;#39;ve defined them. This is what I mean by drawing boxes. We have decided which concepts &lt;a href=&quot;https://www.youtube.com/watch?app=desktop&amp;amp;v=fXW-QjBsruE&quot;&gt;deserve a name&lt;/a&gt; and we&amp;#39;ve defined our terms to describe things we think are important.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;We give names to stuff, and if they catch on we put them in dictionaries with the word &lt;em&gt;noun&lt;/em&gt; next to them. But are all of these nouns an inventory of the Universe or an inventory of things &lt;em&gt;we&lt;/em&gt; made?&lt;br/&gt;
– &lt;a href=&quot;https://youtu.be/fXW-QjBsruE?si=syru8ENohhNE_npc&amp;amp;t=328&quot;&gt;Vsauce&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;As we continue to accelerate the pace at which we can implement technologies and shade in the boundaries of human knowledge, it&amp;#39;s important to remember that, ultimately, we&amp;#39;re the ones in control of the system because we define the boundaries of discussion. We make up the words and thereby impose our definitions on the world. That is the irreplaceable value we provide that no model can ever hope to replace.&lt;/p&gt;&lt;p&gt;It might feel like a very abstract role to us now, but so would be modern formal logic to the scholars of early-modern Europe who worried that &lt;a href=&quot;https://nautil.us/the-inventor-of-the-thinking-machine-didnt-worry-neither-should-you-1282097#:~:text=In%201642%20the,science%2C%20and%20philosophy.&quot;&gt;a calculator would replace them&lt;/a&gt;. It didn&amp;#39;t. Instead they went on to focus on more important things.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Hello? Where Is Everybody? | Brain Baking</title>
<link>https://brainbaking.com/post/2026/10/hello-where-is-everybody/</link>
<enclosure type="image/jpeg" length="0" url="https://brainbaking.com/logo.jpg"></enclosure>
<guid isPermaLink="false">8kaM4v7tSJPPAtdyCQClUN9VNVCfua-cNZmYcg==</guid>
<pubDate>Mon, 26 Oct 2026 17:26:57 +0000</pubDate>
<description>The shopping centre we find ourselves in also has an IKEA nearby. My daughter &amp; I pop in to walk …</description>
<content:encoded>&lt;p&gt;The shopping centre we find ourselves in also has an IKEA nearby. My daughter &amp;amp; I pop in to walk through the isles that house the teddy bears. She picks out a giraffe that now lives by the name &lt;em&gt;Giraffa&lt;/em&gt; or just &lt;em&gt;Raffa&lt;/em&gt;. For once, we don’t really need anything else in this lovely Swedish store so we head downstairs to find the checkout registers. Instead of encountering a friendly face that helps with the payment process, we’re greeted with closed registers resulting in too long lines. The only open ones are self-scanners. There goes the possibility for some lightweight banter.&lt;/p&gt;&lt;p&gt;Our fridge is empty. We bike to the nearest supermarket for some quick midweek resupplies. No long queues this time, but just as little employees waiting for us at the checkout: only the occasional self-scan verification makes chitchat possible. I see that they closed yet another “human checkout lane”. &lt;em&gt;The System Works&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;On one of the campuses where I teach, as part of an experiment, a small physical Amazon store has been opened. This is one of those weird zero personnel stores where everything operates through cameras and image recognition. It feels creepy to even be there. It was also ridiculously expensive and the experiment has been put on hold, but during my trip to the USA I encountered more of these… things? Supply &lt;em&gt;factories&lt;/em&gt;? &lt;em&gt;Stores&lt;/em&gt;? I don’t know what to call them.&lt;/p&gt;&lt;p&gt;My ISP is giving me a headache by wrongly configuring something in the remote-controlled router. This wasn’t the first time it happened, but this time, I can’t seem to fix it myself. So I dial the free support number, only to be greeted with too many robot-controlled menu options. Press 1 for Dutch. Press 2 for other requests. Press 3 if you really really need to really talk to a human—are you sure? Press 6 to confirm. Press 7 to confirm. Please wait 20 more minutes.&lt;/p&gt;&lt;p&gt;After ten minutes, I disconnect in frustration and turn to the internet. There’s a FAQ page, a support page pointing to the FAQ page, and of course a lovely genAI-controlled chatbot. After “reasoning” (ha!) with the bot for a few minutes, it suggests to call the number I already called 30 minutes ago. I try to look for an email address but can’t find one. My &lt;em&gt;fuck this, I’ll solve it myself&lt;/em&gt; attitude ultimately fixed the problem at the cost of a portion of my social self.&lt;/p&gt;&lt;p&gt;I mentor a couple of students working their way through various internships in the IT industry. As the point of contact for the school, I head over there three times: an initial conversation to set the stage, a quick check-in to validate if everything is still going well, and a more formal evaluation meeting to hand out grades together with the employer. I look up where I need to be, bike over there, find the correct building but not the correct floor. I missed the info desk at the entrance—oh wait, it’s just…  not there. There’s also no information on the elevator as to which company operates on which floor.&lt;/p&gt;&lt;p&gt;I eventually find the info I need in a hallway and arrive at the reception desk of the company. Again, nobody home. I can see people clutched behind their laptop in adjacent rooms through the windows. I resist the urge to wave and look around. The glass door towards the company’s hallway is locked. There’s an iPad bolted on the reception desk where I have to register myself. The form demands my email address (I provide my work one as they have it anyway) and a telephone number (Yeah right! What about &lt;code&gt;123456789&lt;/code&gt;?). It states my contact will pick me up soon. I wait. I again resist the urge to wave.&lt;/p&gt;&lt;p&gt;After 10 minutes, the person picks me up and walks me towards the meeting room. I mention the awkward impersonal registration process; he assures it works perfectly. As a software professional myself, knowing the many points of failure, I don’t believe him. He admits to being a bit later because the system works with Slack messages but he was monitoring the wrong channel. I wished I did wave.&lt;/p&gt;&lt;p&gt;This depersonalising of receptions to “optimise” employee efficiency leaves a very bad taste in the mouth of the visitors. I biked home confused and still feel a little sad when thinking about it. How hard can it be to put a human there to, you know, greet the visitor with, you know a smile instead of an iPad that demands personal data that’s not relevant to the visit? In the form, I had to select my contact person (that gets notified with a Slack message) which is a simple &lt;code&gt;&amp;lt;select/&amp;gt;&lt;/code&gt; that revealed every employee’s first name and last name. Oops?&lt;/p&gt;&lt;p&gt;On top of that, the “the person is notified, sit back and relax!” wasn’t relaxing at all: I know how async backend messages work: the frontend shows “relax dude!” but the backend says &lt;code&gt;500&lt;/code&gt; and your message never reaches the contact person. Just raise that hand. Wave. If a receptionist calls someone, I can &lt;em&gt;hear&lt;/em&gt; them making the call and I &lt;em&gt;know&lt;/em&gt; I can relax: the message has been passed. Smile.&lt;/p&gt;&lt;p&gt;Hello? Where is everybody? This evolution depresses me. I want to see real (not generated) faces and talk to someone real (not generated). The rise of these annoying &lt;em&gt;CAN I HELP YOU WITH ANYTHING??&lt;/em&gt; chatbots on corporate websites replacing a simple contact form only adds to the irritation. I can certainly relate to the increased amount of spam received through these forms, but I pay you every month enough to keep the lights on. The least I expect in return is a humane customer service experience.&lt;/p&gt;&lt;p&gt;
			        
			        	
                
                    &lt;kbd&gt;&lt;a href=&quot;https://brainbaking.com/categories/braindump&quot;&gt;braindump&lt;/a&gt;&lt;/kbd&gt;
                
                 
			        
				    
			  	&lt;/p&gt;</content:encoded>
</item>
<item>
<title>「做个人」 – So!azy</title>
<link>https://blog.solazy.me/20261025/</link>
<enclosure type="image/jpeg" length="0" url="https://bear-images.sfo2.cdn.digitaloceanspaces.com/sol/fc99d67bf9584727896a2bcb8d799ad0.webp"></enclosure>
<guid isPermaLink="false">76ULnvJlWOd355ojrf_hXPppCpwa9t0Ro4aWvQ==</guid>
<pubDate>Sun, 25 Oct 2026 17:05:38 +0000</pubDate>
<description>今天这个选题是压了好一阵子的了，最近思考的很完备，索性写出来</description>
<content:encoded>&lt;h1&gt;「做个人」&lt;/h1&gt;&lt;p&gt;
            &lt;i&gt;
                &lt;time&gt;
    25 Oct, 2026
&lt;/time&gt;
            &lt;/i&gt;
        &lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://bear-images.sfo2.cdn.digitaloceanspaces.com/sol/fc99d67bf9584727896a2bcb8d799ad0.webp&quot; alt=&quot;fc99d67bf9584727896a2bcb8d799ad0&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;前阵子在路上听了一期「日谈公园」的播客，请的嘉宾是我一直很喜欢的文学教育工作者赵毓龙。那期节目聊的是明清小说里的生日宴，顺着话头讲到了《金瓶梅》第二十九回「吴神仙冰鉴定终身」。&lt;/p&gt;&lt;p&gt;书里的场景是这样的：守备府周大人派人给西门庆送来一位游方道士吴神仙，说是能通风鉴、善究子平。西门庆当时刚满 29 岁，正是鲜花着锦、权势日盛的当口。吴神仙先给他排了八字，一通好话铺垫下来，说他目下有「平地登云之喜，添官进禄之荣」，紧接着又得贵子。西门庆自然受用，追问往后的运限。吴神仙便交了实底，说他八字里阴水太多，往后到了甲子运，「不出六六之年，主有呕血流脓之灾，骨瘦形衰之病」。&lt;/p&gt;&lt;p&gt;六六之年就是 36 岁。换作任何一个正常人，在 29 岁的年纪听见算命先生说自己活不过 36 岁，哪怕心里不信，脸上多少也得挂点霜。但西门庆的反应非常耐人寻味。他没有深究那句要命的判词，反而紧接着问了一句「目下如何」，以及「命中还有败否」。吴神仙顺着他的心思回道，眼下家里那点小吵闹不足为灾，至于家业衰败，「年赶着月，月赶着日，实难矣」。书里紧跟着写了七个字：「西门庆听了，满心欢喜。」&lt;/p&gt;&lt;p&gt;读到这里，我们很容易生出一种优越感，觉得这人怎么蠢得如此彻底。人家明明已经在暗示你纵欲过度、日后要精尽人亡，你却自动过滤掉死期，只把那句「呕血流脓」当成日后难免的一场小灾，只要眼下官运财运不败，就敢「满心欢喜」。&lt;/p&gt;&lt;p&gt;赵毓龙在节目里聊到这一段时，抛出了一个让我印象很深的判断：看书和看人一样，得「做个人」。&lt;/p&gt;&lt;p&gt;什么叫「做个人」？就是别总站在已知结局的岸上，用毫无成本的聪明去嘲笑水里的人。我们作为读者，手里攥着整本书的目录，开了上帝视角，跟西门庆那点家业、官位和声色犬马没有任何利益牵扯，自然能一眼看穿吴神仙的话中意。但如果你把上帝视角收起来，真正钻进西门庆的皮囊里看一眼：一个 29 岁的暴发户，刚刚打通了京城蔡太师的关节，眼看就要加官进爵，家里妻妾成群，银子像流水一样进账。在这个节骨眼上，你让他去相信自己再过几年就要骨瘦形衰而死，这在人性上是根本做不到的。&lt;/p&gt;&lt;p&gt;人永远只能听见自己想听的话，更准确地说，人只能听见和自己当下处境相匹配的话。所谓的「当局者迷」，从来不是因为局里的人智商突然掉线了，而是他被巨大的既得利益、感官刺激和惯性推着走。在那个具体的场域里，承認风险意味着要立刻推翻自己赖以生存的快感来源，这种代价太大了，大到大脑会自动启动防御机制，把致命的警告翻译成无伤大雅的插曲。&lt;/p&gt;&lt;p&gt;我后来琢磨了一下，发现我们在日常工作和生活里，其实每天都在犯这种「不做人」的毛病。&lt;/p&gt;&lt;p&gt;比如在业务复盘或者跨部门协作的时候，我们特别容易扮演那个冷眼旁观的读者。当一个项目彻底烂尾，或者一个明显的隐患最终爆雷，总有人跳出来摊手，说「我早就看出来这条路走不通」，或者「这么低级的坑怎么会踩进去」。站在事后，或者站在不背核心 KPI 的外围，谁都能当那个口吐莲花的吴神仙，把逻辑链条拆得滴水不漏。&lt;/p&gt;&lt;p&gt;但这种聪明是很廉价的。你之所以看得清楚，往往只是因为你不在那个火坑里。你不需要在每天下午 6 点前面对客户的连环追问，不需要在资源极度匮乏的前提下强行拼凑出一个可交付的方案，也没有被某种短期的业绩虚荣冲昏头脑。当你不承担对方的恐惧、贪婪和考核压力时，你给出的那种居高临下的指点，本质上就是一种缺乏边界感的傲慢。&lt;/p&gt;&lt;p&gt;反过来想，赵毓龙说的「做个人」，在我的工作方法论里，其实对应着一种更冷酷也更务实的判断力。&lt;/p&gt;&lt;p&gt;承认人性在具体处境下的局限，不是为了替烂结果找借口，也不是为了搞无原则的共情。正因为我知道一个人在顺风顺水或者极度焦虑时，必然会像西门庆一样选择性失聪，我才彻底放弃了靠「苦口婆心的提醒」去改变他人的幻想。&lt;/p&gt;&lt;p&gt;在职场里，如果你发现一个人正处于某种狂热的惯性中，或者正在用极其拧巴的方式掩盖问题，你去跟他讲长远的风险、讲底层的逻辑，大概率是对牛弹琴。他也会像西门庆问「目下如何」一样，只要眼下能糊弄过去，他就会继续「满心欢喜」地往前冲。&lt;/p&gt;&lt;p&gt;想明白这一点之后，我处理类似局面的方式变得简单了很多。&lt;/p&gt;&lt;p&gt;第一，在评价别人之前，先看一眼他的筹码和处境。如果我不在牌桌上，没押上身家，我就闭嘴，不赚那份事后诸葛亮的口舌便宜。第二，如果我是那个必须为结果兜底的人，我就绝不把希望寄托在当事人的「自我觉醒」上。既然知道局中人注定会过滤掉警告，那就别费劲去做吴神仙，直接用机制、权限和明确的止损线去切掉他的惯性。&lt;/p&gt;&lt;p&gt;看透一个人的局限而不去嘲弄，这是教养；知道局限无法靠说教克服，于是直接动手改规则，这是专业。所谓的「做个人」，大概就是把这两件事分清楚。&lt;/p&gt;&lt;p&gt;
                
                    &lt;a href=&quot;https://blog.solazy.me/blog/?q=daily&quot;&gt;#daily&lt;/a&gt;
                
            &lt;/p&gt;</content:encoded>
</item>
<item>
<title>为什么有人不怕把事做砸 – So!azy</title>
<link>https://blog.solazy.me/20261023/</link>
<enclosure type="image/jpeg" length="0" url="https://bear-images.sfo2.cdn.digitaloceanspaces.com/sol/rishabh-dharmani-x0gw9yspcr4-unsplash.webp"></enclosure>
<guid isPermaLink="false">YgCutRTJoAzssMUxafz95MOdx00_w0N24w1PeQ==</guid>
<pubDate>Fri, 23 Oct 2026 17:48:17 +0000</pubDate>
<description>今天想接着昨天讲得继续来聊……</description>
<content:encoded>&lt;h1&gt;为什么有人不怕把事做砸&lt;/h1&gt;&lt;p&gt;
            &lt;i&gt;
                &lt;time&gt;
    23 Oct, 2026
&lt;/time&gt;
            &lt;/i&gt;
        &lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://bear-images.sfo2.cdn.digitaloceanspaces.com/sol/rishabh-dharmani-x0gw9yspcr4-unsplash.webp&quot; alt=&quot;rishabh-dharmani-x0gw9YspcR4-unsplash&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;昨天写完《&lt;a href=&quot;https://blog.solazy.me/20261022/&quot;&gt;睡得着觉的人&lt;/a&gt;》，我其实还有个问题没往深处想：面对自己交出去的烂摊子，为什么有些人不仅睡得着，甚至能长期容忍自己处于这么差的状态里？&lt;/p&gt;&lt;p&gt;按常理说，人是有羞耻心的。做出不体面的东西，哪怕别人不骂，自己看着也该觉得刺眼。但在实际共事中，我确实见过不少对「差」完全脱敏的人。我后来琢磨了一下，那些能心安理得跟自己的糟糕产出共处的人，大抵逃不出下面这两类。&lt;/p&gt;&lt;p&gt;第一类，是永远有退路的人。&lt;/p&gt;&lt;p&gt;很多年前，我其实不太相信这个世界上真有一路走来没受过什么苦、也没遇到过真正困境的人。但最近这几年，我在职场和生活里实打实撞见过好几个。他们有着非常顺遂的童年，家境殷实，从小到大被保护得极好。跟他们打交道，你能明显感觉到一种天真的松弛感。在他们的认知里，真实、快乐、美好就像是这个世界理所应当提供的空气，是出厂自带的默认设置。&lt;/p&gt;&lt;p&gt;这种顺遂给他们垫了一层极厚的底。不管眼下在社会里遭遇了什么挫折，或者手头的工作捅了多大的篓子，他们的潜意识里始终有一个声音在兜底：我其实没必要那么拼，大不了就不干了。&lt;/p&gt;&lt;p&gt;因为有随时离场的底气，工作对他们来说更像是一场体验，而不是立身之本。把事情搞砸了，不会触发他们的生存危机，自然也就引不起足够强烈的羞耻感。你跟他们讲职业底线、讲交付标准，在他们听来可能就像是在一个周末下午非要拉着人跑马拉松一样不可理喻。他们不是故意要当坏人，只是单纯没有那个把事情死磕到底的生存必要。&lt;/p&gt;&lt;p&gt;如果说第一类人是因为「不痛」所以不在乎，那第二类人就纯粹是缺少敬畏之心。&lt;/p&gt;&lt;p&gt;这类人我早在 9 月份写《&lt;a href=&quot;https://blog.solazy.me/20260915/&quot;&gt;敬畏之心&lt;/a&gt;》的时候就提过，今天还是忍不住要再拎出来说。他们在职场里通常表现得极其自信，甚至可以说是盲目乐观。不管接手多复杂的事，第一反应永远是「这有什么难的」。&lt;/p&gt;&lt;p&gt;但我一直觉得，正常的逻辑应该是，一个人的能力和认知积累到了某个水位，看待问题清楚了，手里有活儿了，那种笃定的状态自然就出来了，根本不需要再去刻意建立什么自信。而这些人完全把路径搞反了。他们在既没有专业能力、也没有基本行业认知的时候，先把「自信」给备齐了。甚至我觉得用「自信」这个词来形容他们，都是对这个词的一种抹黑。&lt;/p&gt;&lt;p&gt;因为对事情的复杂程度毫无概念，对专业性没有半点敬畏，他们根本看不见自己做出来的东西和真正的好东西之间隔着多远的距离。一个连「好」都没见过、也不承认有「好」存在的人，你指望他因为自己做得「差」而感到羞愧，本身就是一件不可能的事。他们看着自己满是漏洞的交付物，心里想的可能还真是「我已经做得很完美了」。&lt;/p&gt;&lt;p&gt;想明白这两点之后，我反而少了很多无谓的愤怒。&lt;/p&gt;&lt;p&gt;以前遇到那种把活儿干得稀碎还能谈笑风生的人，我总会下意识想去纠正，想拉着对方复盘，试图唤醒他们身上的那点职业自尊。现在我完全放弃了这种念头。一个人的退路是家庭给的，一个人的盲目是长年累月的认知缺陷喂出来的，这都不是靠一两次绩效面谈或者几句重话就能扭转的东西。&lt;/p&gt;&lt;p&gt;在合作和招人的时候，我现在只看一个很朴素的指标：这个人到底痛不痛。他会不会因为一个低级错误在深夜感到焦躁，会不会对未知的领域保持一点点试探的谨慎。如果没有，不管他看起来多么阳光开朗，或者在面试时表现得多么有冲劲，我都会选择直接绕开。毕竟大家出来工作是为了把事做成，不是为了给有退路的人提供游乐场，更不是为了给盲目的人交学费。&lt;/p&gt;&lt;p&gt;
                
                    &lt;a href=&quot;https://blog.solazy.me/blog/?q=daily&quot;&gt;#daily&lt;/a&gt;
                
            &lt;/p&gt;</content:encoded>
</item>
<item>
<title>Please don&#39;t mess with links:</title>
<link>https://maurycyz.com/misc/real_links/</link>
<guid isPermaLink="false">kIEN9KVEpGaYjAsXbDBiIPxqxZ2o6Zw5HinIiw==</guid>
<pubDate>Fri, 23 Oct 2026 07:14:53 +0000</pubDate>
<description>Please don&#39;t mess with links:</description>
<content:encoded>&lt;h1&gt;&lt;em&gt;Please don&amp;#39;t mess with links:&lt;/em&gt;&lt;/h1&gt;&lt;b&gt;&lt;time&gt;2026-05-31&lt;/time&gt;&lt;/b&gt;&lt;p&gt;

A link is just a button that takes you somewhere when you click it right?
&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;center&gt;&lt;span&gt;100% legit link&lt;/span&gt;&lt;/center&gt;&lt;p&gt;
Except that&amp;#39;s a pale, shallow imitation of a link.
A real link can be:
&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Opened in a new tab. (ctrl)&lt;/li&gt;
&lt;li&gt;... or a fresh window. (shift)&lt;/li&gt;
&lt;li&gt;... or saved as a file (alt).&lt;/li&gt;
&lt;li&gt;Copied as a URL (right click)&lt;/li&gt;
&lt;li&gt;Used with the keyboard (tab + enter)&lt;/li&gt;
&lt;li&gt;Seen by tools like search engines and screen readers.&lt;/li&gt;
&lt;li&gt;Hovered over to see the URL.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;
... none of which work with a button.
&lt;/p&gt;&lt;p&gt;
&lt;em&gt;Another common offense&lt;/em&gt; is to use a real link, but hook the click event to open a popup.
However, with a real &amp;lt;a target=&amp;quot;_blank&amp;quot;&amp;gt; link, I can:
&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;See the loading progress...&lt;/li&gt;
&lt;li&gt;... or/and cancel it.&lt;/li&gt;
&lt;li&gt;... see descriptive error pages and retry if needed.&lt;/li&gt;
&lt;li&gt;Open multiple at once.&lt;/li&gt;
&lt;li&gt;Read the original page while it loads.&lt;/li&gt;
&lt;li&gt;Use my browser&amp;#39;s tabs or/and window manager to organize them.&lt;/li&gt;
&lt;li&gt;Bookmark the page.&lt;/li&gt;
&lt;li&gt;Copy the URL and send it to a friend.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;
... and above all, they are consistent:
&lt;/p&gt;&lt;p&gt;
I&amp;#39;ve long lost count of how many times I&amp;#39;ve accidentally closed the whole site while trying to close a popup that was a little too convincing.
&lt;/p&gt;&lt;p&gt;
It&amp;#39;s also extremely common to click a link with a slow connection, only to be greeted with perpetual spinner.
I have no idea if anything is actually happening or how long it will take.
Worse, it usually covers up the original page so I can&amp;#39;t even read that!
&lt;/p&gt;&lt;p&gt;
&lt;em&gt;Browsers are good at links and loading pages: It&amp;#39;s the whole point.&lt;/em&gt;
&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Don&amp;#39;t use javascript buttons as links.&lt;/li&gt;
&lt;li&gt;Don&amp;#39;t build your own loading animations.&lt;/li&gt;
&lt;li&gt;Link previews should open and close on hover, not on click.&lt;/li&gt;
&lt;li&gt;Don&amp;#39;t open links in javascript popups: Use target=&amp;quot;_blank&amp;quot; instead.&lt;/li&gt;
&lt;/ul&gt;&lt;h1&gt;&lt;em&gt;Other common problems&lt;/em&gt;:&lt;/h1&gt;&lt;p&gt;
Infinite scrolling breaks ctrl-f, bookmarks, the home/end keys and often the back button.
&lt;/p&gt;&lt;p&gt;
You can have a 100k of text on a page:
Browsers will render partially downloaded HTML and the user won&amp;#39;t even notice.
Using a 5 MB javascript framework just do a worse job of downloading text is dumb.
&lt;/p&gt;&lt;p&gt;
To optimize speed, it&amp;#39;s best to minimize the total number of round trips.
Just putting everything in a single TCP connection will always be better than breaking it up because of TCP&amp;#39;s slow start algorithm.
&lt;/p&gt;&lt;p&gt;
&lt;em&gt;Don&amp;#39;t reimplement &amp;lt;details&amp;gt;&lt;/em&gt; which will break search tools and screen readers.
&lt;/p&gt;&lt;p&gt;
... but using fancy CSS to make it look nice is fine.
&lt;/p&gt;&lt;p&gt;
&lt;em&gt;Don&amp;#39;t roll your own date picker&lt;/em&gt; (or any other built-in form inputs)
&lt;/p&gt;&lt;p&gt;
This will always used the user&amp;#39;s preferred date format, covert it to the standard yyyy-mm-dd, and works with the keyboard...
also, it&amp;#39;s one line of code that works with dark mode by default. 
&lt;/p&gt;&lt;h1&gt;&lt;em&gt;Related&lt;/em&gt;:&lt;/h1&gt;&lt;p&gt;
Real links!
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://susam.net/do-not-roll-your-own.html&quot;&gt;https://susam.net/do-not-roll-your-own.html&lt;/a&gt;: Don&amp;#39;t Roll Your Own ...&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://maurycyz.com/misc/13kb/&quot;&gt;/misc/13kb/&lt;/a&gt;: Why using a single big page can actually improve performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;

&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Sending a Silly Meme Is an Act of Love</title>
<link>https://www.theatlantic.com/family/2026/10/send-silly-memes/689077/?utm_source=feed</link>
<guid isPermaLink="false">u3c0sRxD1ThDEMGl9blwJUgxvw3JlU3fLuGcrA==</guid>
<pubDate>Thu, 22 Oct 2026 16:15:25 +0000</pubDate>
<description>The case for a common, occasionally annoying, and secretly sweet digital habit</description>
<content:encoded>&lt;p&gt;At this moment, an untold number of TikTok videos are being sent without commentary to an untold number of group chats. The videos might remind the senders of their mom, their spouse, their high-school best friends. They might strike the recipients as charming—or as smartphone pollution. The meme-sharing never stops.&lt;/p&gt;&lt;p&gt;People have been sending one another memes nearly as long as the web has been worldwide, gathering amusing bits of internet ephemera and texting, emailing, or sharing it on social media with their loved ones. Before it was TikToks and Instagram Reels, it was I Can Has Cheezburger? links posted to Facebook walls. (Even before the internet existed, people engaged in meme-sharing-like behavior: your grandma clipping articles from the newspaper that she thought you might like, for instance.)&lt;/p&gt;&lt;p&gt;As communication goes, sending a meme is one of the lowest-lift—one might even say &lt;em&gt;laziest&lt;/em&gt;—ways to stay in touch. It’s barely a step above not saying anything at all. But a surprisingly large body of &lt;a href=&quot;https://academic.oup.com/jcr/article/52/5/914/8107776?__cf_chl_tk=hx9xtEpTZupwwDRnvsM3gktPWNb.iel8_0hqKhUFD8k-1791913867-1.0.1.1-VzCBbEsE8aBj03Pp0KVRutyHso1n.pjhFD6jLwzI6lc&quot;&gt;research on meme-sharing&lt;/a&gt; has found that it can serve an important function in relationships and bring people closer together.&lt;/p&gt;&lt;p&gt;According to Adam Grant, an organizational psychologist at the University of Pennsylvania, sending memes can be a form of “pebbling”—a term that he, appropriately, saw on social media. It refers to a behavior among gentoo penguins, in which they present potential mates with carefully selected, shiny pebbles. Among humans, giving the gift of a carefully selected, shiny meme &lt;em&gt;can&lt;/em&gt; be a mating behavior, too, or a platonic one.&lt;/p&gt;&lt;p&gt;&lt;i&gt;[&lt;a href=&quot;https://www.theatlantic.com/culture/archive/2023/01/this-is-fine-dog-meme-cultural-relevancy/672838/?utm_source=feed&quot;&gt;Read: The meme that defined a decade&lt;/a&gt;]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;“These aren’t trivial gestures—every pebble is a bid for connection,” Grant writes in his new book, &lt;em&gt;Vibe: The Secrets of Strong Connections in a Lonely World&lt;/em&gt;. Clicking “Share” on a funny Instagram post is hardly on the level of inviting a friend to dinner, as bids for connection go. But neither is it nothing. At minimum, it’s a way of checking in and reminding someone of your relationship. Nicholas Brody, a communication-studies professor at the University of Puget Sound, told me that in unpublished data from his research, he’s found that the most common reason people said they sent memes was just to convey “I’m thinking of you” to the other person.&lt;/p&gt;&lt;p&gt;But for many, the meaning can be deeper than that. People really tend to curate what they send to whom, experts told me, picking and choosing the pebbles that they think the other person will like. For me, cat videos go to my husband, &lt;em&gt;Lord of the Rings&lt;/em&gt; memes to certain friends, nostalgic posts about emo music to different friends, posts about literary drama to my writer friends. This is a way of creating and reinforcing a shared reality, &lt;a href=&quot;https://kuscholarworks.ku.edu/server/api/core/bitstreams/3952c23b-cdfc-46b1-bc15-c74965df1f42/content&quot;&gt;one study on the interpersonal use of memes found&lt;/a&gt;, a sense that we are both on the inside of the specific microculture that is our relationship. (Even those who aren’t meme-sharers themselves do this in many other ways, through inside jokes and private language.) Memes work well for this purpose because they “are so nuanced, and have so many different layers of cultural references and relational meanings,” Brody told me, “that they only really have a lot of power when we already feel really close to somebody.” Indeed, &lt;a href=&quot;https://firstmonday.org/ojs/index.php/fm/article/view/12789/11017&quot;&gt;his research shows&lt;/a&gt; that people mostly send memes to people they know well—to romantic partners and close friends.&lt;/p&gt;&lt;p&gt;The best-case scenario is that a meme opens a door to further sharing. For instance, Grant told me that he recently sent a friend from high school a post of a funny prank he saw—not only because he thought they would appreciate it, but because they themselves were pranksters when they were young. The post launched them into reminiscing about how they used to mash bananas into the door handles of a friend’s car in high school. Rachel Peng, an assistant professor of digital advertising at Louisiana State University, told me that she was inspired to research meme-sending because of her own experience with social anxiety. “Sometimes I send memes,” she said, “to start a conversation. Or sometimes I don’t know what to say but I also want to keep the conversation going.” And even though people tend to use memes most with their nearest and dearest, &lt;a href=&quot;https://cyberpsychology.eu/article/view/38321&quot;&gt;her research has found&lt;/a&gt; that they might be even more beneficial among acquaintances. When you’re just getting to know someone, taking the time to pick out something that reminds you of them is a bigger gesture—even more so if it sparks more back-and-forth.&lt;/p&gt;&lt;p&gt;&lt;i&gt;[&lt;a href=&quot;https://www.theatlantic.com/magazine/2026/11/text-communication-social-obligation/688696/?utm_source=feed&quot;&gt;Read: Forgive the bad texters&lt;/a&gt;]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;But what if the meme receiver doesn’t respond with fond reminiscences? Some Instagram DM threads become wildly lopsided: one person sending meme after meme, the other hearting no more than every tenth one. That sort of thing could be annoying. “There is such a thing as spamming people with random junk from the internet,” Grant said. But if the memes are lovingly curated, it could still be a net positive for the relationship, even if the meme receiver just chuckles privately without responding. “If we both get the joke, it’s still a bit like a little moment of connection, right?” Peng said.&lt;/p&gt;&lt;p&gt;“One of the key things in relational maintenance is that we want assurances that this other person values our friendship and our relationship just as much as us,” Brody added. But “it doesn’t always have to be a meme for a meme.” Just remember that if your friend sent you 15 memes in a day, it means they thought of you 15 times that day. So drop them the occasional &lt;em&gt;lol&lt;/em&gt; or heart emoji just to show you’re thinking of them too.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Rendering untrusted HTML email, safely | The Making of Close</title>
<link>https://making.close.com/posts/rendering-untrusted-html-email-safely/</link>
<guid isPermaLink="false">JULIYAiHBu7--z4UShE1ywCadrSDOv8wuAcyRg==</guid>
<pubDate>Tue, 20 Oct 2026 17:06:04 +0000</pubDate>
<description>One of the earliest core features we built in Close was our</description>
<content:encoded>&lt;p&gt;One of the earliest core features we built in Close was our
&lt;a href=&quot;https://close.com/emailing/&quot;&gt;email sync feature&lt;/a&gt;, which allows Close to
automatically pull in email communication between your sales team and your sales
contacts and display them for your team to see. We present a unified timeline of
all communication (emails, calls, SMS, etc.) with a sales lead in one place for
your team.&lt;/p&gt;&lt;p&gt;This feature required that we build a way to display email in our web app –
&lt;em&gt;safely&lt;/em&gt;, without security concerns that typically come with naively rendering
untrusted HTML
(&lt;a href=&quot;https://owasp.org/www-community/attacks/xss/#Stored_and_Reflected_XSS_Attacks&quot;&gt;Stored XSS Attacks&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;We launched our ability to display synced HTML email in 2014, however the
technical side of it is still very relevant and (I think) interesting since our
approach is not one that I&amp;#39;ve seen widely used.&lt;/p&gt;&lt;p&gt;In the end, we found a way to, exclusively on the client-side (in web browsers),
render untrusted HTML email safely inside our single-page application (written
originally with Backbone.js, now mostly React). Here we&amp;#39;ll discuss a few
approaches we had to consider and how we solved this problem.&lt;/p&gt;&lt;p&gt;For example, we can display an IMAP-synced email thread like this:&lt;/p&gt;&lt;p&gt;&lt;span&gt;
      &lt;a href=&quot;https://making.close.com/static/59bc283663f231da9d5d10687803846a/18650/email.png&quot;&gt;
    
  &lt;picture&gt;
          
          
          &lt;img src=&quot;https://making.close.com/static/59bc283663f231da9d5d10687803846a/fe486/email.png&quot; alt=&quot;email&quot; title=&quot;&quot;/&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;&lt;h1&gt;HTML vs Plaintext?&lt;/h1&gt;&lt;p&gt;While many emails do come with a plaintext variant, we had to immediately
dismiss the idea of only displaying plaintext email, as convenient as that would
have been from a security perspective. Many emails don&amp;#39;t have a reasonable
plaintext alternative, and users simply expect to be able to view HTML formatted
email as they were designed.&lt;/p&gt;&lt;p&gt;Some emails &lt;em&gt;only&lt;/em&gt; have a plaintext variant. In those cases we can render the
plaintext content pretty simply in our web app: effectively just convert new
lines into &lt;code class=&quot;language-text&quot;&gt;&amp;lt;br&amp;gt;&lt;/code&gt; tags and convert URLs into links.&lt;/p&gt;&lt;p&gt;But most of the interesting engineering/security concerns are around rendering
untrusted HTML content (in this case, email content) safely, which is where the
remainder of this blog post will focus.&lt;/p&gt;&lt;h1&gt;Main goals and concerns&lt;/h1&gt;&lt;p&gt;Our main goals were the following:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Display HTML email, not just plaintext&lt;/li&gt;
&lt;li&gt;Display &amp;quot;full&amp;quot; HTML email. We care about much more than just a few simple tags
like &lt;code class=&quot;language-text&quot;&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;&amp;lt;i&amp;gt;&lt;/code&gt;, but rather want to support displaying sophisticated
email styles (including custom &lt;code class=&quot;language-text&quot;&gt;style&lt;/code&gt; tags) that you often see in
well-designed HTML email newsletters, calendar invitations, etc.&lt;/li&gt;
&lt;li&gt;We want to render emails within our web application, without any conflicts of
our CSS leaking in or the email CSS leaking out.&lt;/li&gt;
&lt;li&gt;In addition to CSS styles, we also want to display images, expect links to
work, etc.&lt;/li&gt;
&lt;li&gt;Most important: Do not let any JavaScript run. Otherwise we run the risk of an
attacker taking over our user&amp;#39;s Close account by stealing cookies, or a number
of other Very Bad™️ things.&lt;/li&gt;
&lt;/ul&gt;&lt;h1&gt;Finding a solution…&lt;/h1&gt;&lt;h2&gt;Saying No to HTML Sanitization&lt;/h2&gt;&lt;p&gt;While there may be some rock-solid libraries out there that can take untrusted
HTML content and make it completely safe for rendering in HTML, there were a lot
of potential downsides to this idea.&lt;/p&gt;&lt;p&gt;First off, in 2014, we didn&amp;#39;t immediately trust any of them. HTML sanitization
libraries often rely on parsing HTML with regex, which is a
&lt;a href=&quot;https://stackoverflow.com/a/1732454/137067&quot;&gt;notoriously bad idea&lt;/a&gt;. We
absolutely didn&amp;#39;t want to be trying to maintain a library like this ourselves,
or have to worry about some unhandled edge case that could lead to a major
security vulnerability.&lt;/p&gt;&lt;p&gt;Additionally, unlike other use cases (e.g. rendering a blog comment which may
contain just some basic markup for bolding text), we felt like we needed to
render complex (heavily styled) HTML emails properly, just like you&amp;#39;d see in
Gmail or other modern email clients, so we couldn&amp;#39;t default to a tiny whitelist
of tags or supported attributes.&lt;/p&gt;&lt;p&gt;Finally, HTML sanitization on its own wouldn&amp;#39;t be enough, because we want to
render the email within an existing web app, and we don&amp;#39;t want its styles
affecting the styles of the rest of the web app. There&amp;#39;s a well-known solution
to this – iframes – that we could have used to help here.&lt;/p&gt;&lt;p&gt;Once we explored iframes, however, we realized they could do everything we
needed already on their own…&lt;/p&gt;&lt;h2&gt;What can iframes do for us?&lt;/h2&gt;&lt;p&gt;Most web developers know that an &lt;code class=&quot;language-text&quot;&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; can render a web page in a fairly
isolated fashion. Certainly they can solve the issue of our web app styles
incorrectly affecting an email&amp;#39;s styles (or vice versa).&lt;/p&gt;&lt;p&gt;But we still have that pesky issue of JavaScript.&lt;/p&gt;&lt;h3&gt;Uncommon but helpful iframe attributes&lt;/h3&gt;&lt;p&gt;There are a number of lesser known iframe attributes that can be very helpful.
Let&amp;#39;s take a look at a few.&lt;/p&gt;&lt;h4&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;srcdoc&lt;/code&gt;&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Most commonly iframes point to a &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; webpage URL – either on the same origin
or different origin. But since Close is a Single Page Application and our
frontend would already be fetching data about the email from our
&lt;a href=&quot;https://developer.close.com/&quot;&gt;REST API&lt;/a&gt; (and could include the email body
itself), we discovered that this attribute allowed us to inject HTML content
into an iframe (with all the typical iframe benefits) without needing that
content to be served by a separate page.&lt;/p&gt;&lt;p&gt;So rather than having to do something like:&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;iframe src=&amp;quot;/email/body/?email_id=EMAIL_ID_HERE&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;... which would have required us to setup an additional endpoint, we could
simply display the HTML we already had:&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;iframe srcdoc=&amp;quot;UNTRUSTED_HTML_HERE&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Neither approach is particularly more or less secure than the other. Both make
you still think about &amp;quot;what about script execution&amp;quot; and consider the &amp;quot;same
origin&amp;quot; vs. &amp;quot;different origin&amp;quot; options (e.g. we might have needed a separate
domain and then have to pass some kind of token for authentication). We chose
&lt;code class=&quot;language-text&quot;&gt;srcdoc&lt;/code&gt; because it worked and was easiest for our setup.&lt;/p&gt;&lt;p&gt;For the value that we inject into the &lt;code class=&quot;language-text&quot;&gt;srcdoc&lt;/code&gt;, we actually wrap the HTML email
in a little HTML, with two main goals:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Give email bodies some sane default styles, and make them fit into the
look-and-feel of our web app by default.&lt;/li&gt;
&lt;li&gt;Put &lt;code class=&quot;language-text&quot;&gt;target=&amp;quot;_blank&amp;quot;&lt;/code&gt; on all links by default (via a &lt;code class=&quot;language-text&quot;&gt;&amp;lt;base&amp;gt;&lt;/code&gt; tag), since we
never want a user clicking an email link to load a new webpage in the iframe,
and this is also a convenient way for us to apply this behavior to all links
without having to traverse the email&amp;#39;s HTML.&lt;/li&gt;
&lt;li&gt;Apply a &lt;a href=&quot;https://content-security-policy.com/&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Content-Security-Policy&lt;/code&gt;&lt;/a&gt;
&lt;code class=&quot;language-text&quot;&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag instructing the iframe document to avoid executing any JavaScript
whatsoever. (If we used a hosted page with &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;srcdoc&lt;/code&gt;, this
would be done with an HTTP Header instead).&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta http-equiv=&amp;quot;Content-Security-Policy&amp;quot; content=&amp;quot;script-src &amp;#39;none&amp;#39;&amp;quot; /&amp;gt;
    &amp;lt;base target=&amp;quot;_blank&amp;quot; /&amp;gt;
    &amp;lt;style&amp;gt;
      body {
        margin: 0;
        font:
          13px -apple-system,
          system-ui,
          &amp;#39;Segoe UI&amp;#39;,
          Roboto,
          Oxygen-Sans,
          Ubuntu,
          Cantarell,
          &amp;#39;Helvetica Neue&amp;#39;,
          sans-serif,
          &amp;#39;Apple Color Emoji&amp;#39;,
          &amp;#39;Segoe UI Emoji&amp;#39;,
          &amp;#39;Segoe UI Symbol&amp;#39;,
          sans-serif;
        overflow-y: hidden;
      }
      html:not(.x),
      body:not(.x) {
        height: auto !important;
      }
      p:first-child {
        margin-top: 0;
      }
      p:last-child {
        margin-bottom: 0;
      }
      a[href] {
        color: #3781b8;
        text-decoration: none;
      }
      a[href]:hover {
        text-decoration: underline;
      }
      blockquote[type=&amp;#39;cite&amp;#39;] {
        margin: 0 0 0 0.8ex;
        border-left: 1px #ccc solid;
        padding-left: 1ex;
      }
      img {
        max-width: 100%;
      }
      ul,
      ol {
        padding: 0;
        margin: 0 0 10px 25px;
      }
      ul {
        list-style-type: disc;
      }
    &amp;lt;/style&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    ${bodyHtml}
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;sandbox&lt;/code&gt;&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;This attribute is the heart of our security model. By adding this attribute, it
adds a whole bunch of restrictions to the iframe document, including preventing
any JavaScript from running! Learn more about what&amp;#39;s blocked
&lt;a href=&quot;https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox&quot;&gt;here&lt;/a&gt;
and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe&quot;&gt;here&lt;/a&gt;.
The &lt;code class=&quot;language-text&quot;&gt;sandbox&lt;/code&gt; attribute allows you to opt back in specific behaviors that are
blocked by default. We only allow:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;allow-popups&lt;/code&gt; – We add &lt;code class=&quot;language-text&quot;&gt;target=&amp;quot;_blank&amp;quot;&lt;/code&gt; to all of them.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;allow-popups-to-escape-sandbox&lt;/code&gt; - So that external webpages opened via a link
actually function properly.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;allow-same-origin&lt;/code&gt; – We need this for our web app to detect the height of
iframe&amp;#39;s content. This would be dangerous (and defeat the purpose of
&lt;code class=&quot;language-text&quot;&gt;sandbox&lt;/code&gt;) if we also allowed scripts to run by also including
&lt;code class=&quot;language-text&quot;&gt;allow-scripts&lt;/code&gt;, however it&amp;#39;s harmless on its own.&lt;/li&gt;
&lt;/ul&gt;&lt;h4&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;csp&lt;/code&gt;&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;We add a Content Security Policy to the iframe with a value of
&lt;code class=&quot;language-text&quot;&gt;script-src &amp;#39;none&amp;#39;&lt;/code&gt; as an additional mechanism to avoid any JavaScript from
running in the iframe. This is mostly duplicative with &lt;code class=&quot;language-text&quot;&gt;sandbox&lt;/code&gt; but provides an
extra layer of protection in
&lt;a href=&quot;https://caniuse.com/#feat=mdn-api_htmliframeelement_csp&quot;&gt;browsers&lt;/a&gt; that support
it.&lt;/p&gt;&lt;p&gt;As you can see, we have some overlap in coverage here (e.g. 3 separate features
to avoid JavaScript running). We have learned of particular browser bugs where
there were temporary limitations in any one of these indvidiual approaches. A
reminder that security in layers is often best.&lt;/p&gt;&lt;h2&gt;Bringing it together...&lt;/h2&gt;&lt;h2&gt;Handling unsupported browsers&lt;/h2&gt;&lt;p&gt;As soon as we made the decision to rely on &lt;code class=&quot;language-text&quot;&gt;&amp;lt;iframe sandbox&amp;gt;&lt;/code&gt; as our primary
safety mechanism, we also had to consider users with browsers who didn&amp;#39;t have
this safety mechanism, so that we didn&amp;#39;t put their accounts at risk. Feature
detection to the rescue:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;// Don&amp;#39;t show HTML at all if they are using a browser that doesn&amp;#39;t support &amp;lt;iframe sandbox&amp;gt;
// since our security model relies on it to prevent XSS.
// (And the basic functionality relies on &amp;lt;iframe srcdoc&amp;gt;)
const iframe = document.createElement(&amp;#39;iframe&amp;#39;);
const isHtmlEmailSupported = &amp;#39;sandbox&amp;#39; in iframe &amp;amp;&amp;amp; &amp;#39;srcdoc&amp;#39; in iframe;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Based on this, we can make sure we &lt;em&gt;only&lt;/em&gt; display the plaintext email variant
(if one exists) or else render a message like &amp;quot;Your browser does not support
displaying email content.&amp;quot;&lt;/p&gt;&lt;h2&gt;Known limitations&lt;/h2&gt;&lt;p&gt;One can envision additional enhancements where we &lt;em&gt;would&lt;/em&gt; want to parse and
modify the email HTML before rendering it. One example would be if we wanted to
try to rewrite and proxy all image URLs
(&lt;a href=&quot;https://gmail.googleblog.com/2013/12/images-now-showing.html&quot;&gt;similar to Gmail&lt;/a&gt;)
to protect our users&amp;#39; privacy.&lt;/p&gt;&lt;p&gt;Similarly, we do have a problem where browsers will show a Mixed Content warning
(since our site is &lt;code class=&quot;language-text&quot;&gt;https://&lt;/code&gt;) after you display an email that includes an
&lt;code class=&quot;language-text&quot;&gt;&amp;lt;img&amp;gt;&lt;/code&gt; with an &lt;code class=&quot;language-text&quot;&gt;http://&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt;. Those warnings are still fairly unobtrusive,
however, but ultimately we should proxy them to be served over https.&lt;/p&gt;&lt;p&gt;So while we may one day layer in additional HTML parsing measures (either
client-side or server-side), and could decide to switch from an
&lt;code class=&quot;language-text&quot;&gt;&amp;lt;iframe srcdoc&amp;gt;&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;&amp;lt;iframe src&amp;gt;&lt;/code&gt;, the other security features mentioned here
would still likely play an important part of safely rendering HTML email.&lt;/p&gt;&lt;h2&gt;Lots of other details to get right&lt;/h2&gt;&lt;p&gt;There were a lot of other details to get right. Each of them could deserve their
own blog post, but here is a summary:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;We have to convert &amp;quot;inline&amp;quot; images (images that are embedded within the email
itself, not referencing an external URL) to be displayable by the web browser.&lt;/li&gt;
&lt;li&gt;We have to deal with understanding quoting parts. We wrote
&lt;a href=&quot;https://github.com/closeio/quotequail&quot;&gt;quotequail&lt;/a&gt; for this. (Mailgun later
open sourced a similar library called
&lt;a href=&quot;https://github.com/mailgun/talon&quot;&gt;talon&lt;/a&gt;). You can see in the screenshot at
the top of this post a little &amp;quot;...&amp;quot; button where the quoted part of the email
is collapsed by default, but expandable.&lt;/li&gt;
&lt;li&gt;We want to avoid the &amp;quot;extra scrollbar&amp;quot; issue you typically experience with
iframes, so we carefully (this is surprisingly tricky) detect the height of
the iframe email contents and then set the iframe to that height, giving it a
seamless look on the page.&lt;/li&gt;
&lt;li&gt;We need to consider how composing email works too. We needed a WYSIWYG editor
for HTML Email that also prevents any XSS. We currently use
&lt;a href=&quot;https://froala.com/wysiwyg-editor/&quot;&gt;Froala Editor&lt;/a&gt; for this, after having
tested many editors for security.&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Thoughts?&lt;/h2&gt;&lt;p&gt;Can you find any flaws in our email rendering security model? Our product and
approach has been audited by third party security firms, however we always
appreciate any reports of security vulnerabilities at
&lt;a href=&quot;mailto:security@close.com&quot;&gt;security@close.com&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Feel free to hit me up at &lt;a href=&quot;https://twitter.com/philfreo&quot;&gt;@philfreo&lt;/a&gt; with any
comments or questions!&lt;/p&gt;&lt;p&gt;– Phil Freo&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Do web components have a future if nobody is writing them? | Read the Tea Leaves</title>
<link>https://nolanlawson.com/2026/10/19/do-web-components-have-a-future-if-nobody-is-writing-them/</link>
<enclosure type="image/jpeg" length="0" url="https://nolanlawson.com/_astro/video-with-controls.C2qozcS-_NiWXm.webp"></enclosure>
<guid isPermaLink="false">t42rGCb_QWdWBjYHNwG2G_YAybY9jWJnhpZwDg==</guid>
<pubDate>Tue, 20 Oct 2026 04:50:11 +0000</pubDate>
<description>With my previous post on “using the platform”, I was surprised that the comments on Hacker News and Lobsters tended to veer toward web components. This…</description>
<content:encoded>&lt;p&gt;With my previous post on &lt;a href=&quot;https://nolanlawson.com/2026/10/03/why-dont-more-developers-use-the-platform/&quot;&gt;“using the platform”&lt;/a&gt;, I was surprised that the comments on &lt;a href=&quot;https://news.ycombinator.com/item?id=49950554&quot;&gt;Hacker News&lt;/a&gt; and &lt;a href=&quot;https://lobste.rs/s/srduzv/why_don_t_more_developers_use_platform&quot;&gt;Lobsters&lt;/a&gt; tended to veer toward web components. This surprised me because I didn’t mention web components at all in the post.&lt;/p&gt;&lt;p&gt;I was less surprised when I did some research and found that the entire “use the platform” mantra was first popularized by &lt;a href=&quot;https://polymer-project.appspot.com/blog/2016-05-26-IO-2016-Recap&quot;&gt;Polymer&lt;/a&gt;, which was Google’s early attempt at a web-components-based JavaScript framework. In 2018 they even called it &lt;a href=&quot;https://www.polymer-project.org/blog/2018-02-26-3.0-preview-paths-and-names&quot;&gt;“our motto”&lt;/a&gt;! So this explains why a lot of people seem to have it burned into their brains that “use the platform” means “use web components.”&lt;/p&gt;&lt;p&gt;Now, one of the reasons I didn’t mention web components in the post is that, in my opinion, they’re actually not a great example of “use the platform” (regardless of the motto’s origins). I instead leaned on examples of HTML and CSS features that tend to be more performant, more accessible, and require far fewer lines of code than the equivalent in JavaScript. This is largely thanks to the advances that the browser vendors and standards bodies (e.g. the &lt;a href=&quot;https://www.w3.org/groups/wg/css/&quot;&gt;CSS Working Group&lt;/a&gt; and &lt;a href=&quot;https://open-ui.org/&quot;&gt;Open UI project&lt;/a&gt;) have made in the past few years.&lt;/p&gt;&lt;h2&gt;Modern Web Guidance&lt;/h2&gt;&lt;p&gt;Web components popped into my head again, though, after a &lt;a href=&quot;https://mamot.fr/@mokobien/117380327572292850&quot;&gt;comment on Mastodon&lt;/a&gt; pointed me to Google’s &lt;a href=&quot;https://developer.chrome.com/docs/modern-web-guidance&quot;&gt;Modern Web Guidance&lt;/a&gt;. I wasn’t aware of this tool before writing the post, but essentially it’s a set of skills that you can give to an agent to nudge them in the direction of using more modern browser features. Essentially, it’s “use the platform” for agents (or at least the Chrome team’s vision of it).&lt;/p&gt;&lt;p&gt;As I was watching &lt;a href=&quot;https://youtu.be/bo3i0FzDUYo&quot;&gt;the demo&lt;/a&gt;, though, I was struck by how hard it is to see where web components fit into the picture. In the presentation, Phil Walton shows how you can use Modern Web Guidance to create a web app that feels more like a native app in terms of following your finger smoothly as you touch the screen, thanks to features like CSS &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Scroll_snap&quot;&gt;scroll snap points&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Scroll-driven_animations&quot;&gt;scroll-driven animations&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;But nowhere in the demo are we really seeing the code – this is pure vibe-coding. And as I watched, I struggled to think of any place where, if I were building Modern Web Guidance myself, I would put instructions to tell the agent, “Hey, you should use custom elements, shadow DOM, or other web component primitives here because it’s going to make the end user experience better.” And that’s because there’s &lt;em&gt;nothing&lt;/em&gt; that web components can really do to make the end user experience better. (Arguably you could say that shadow DOM improves CSS performance, but &lt;a href=&quot;https://nolanlawson.com/2022/06/22/style-scoping-versus-shadow-dom-which-is-fastest/&quot;&gt;I’ve benchmarked this to death&lt;/a&gt;, and you can effectively get the same boost with compile-time CSS scoping, which many frameworks and tools like Svelte, Vue, and Tailwind are already doing.)&lt;/p&gt;&lt;p&gt;So I took a look at the actual &lt;a href=&quot;https://github.com/GoogleChrome/modern-web-guidance&quot;&gt;code&lt;/a&gt; for Modern Web Guidance, and my hunch was confirmed: web components feel like an afterthought. For the first six months of the project’s lifetime, there was almost no mention of web components. This only changed 3 weeks ago when &lt;a href=&quot;https://github.com/GoogleChrome/modern-web-guidance/commit/84ae7251ee919239d5ea85aef25897983f26601e&quot;&gt;a single commit&lt;/a&gt; landed, which mostly provides guidelines for those &lt;em&gt;already using&lt;/em&gt; web components, around the topics of &lt;a href=&quot;https://github.com/GoogleChrome/modern-web-guidance/blob/84ae7251ee919239d5ea85aef25897983f26601e/skills/modern-web-guidance/guides/html/accessible-web-components.md&quot;&gt;accessibility&lt;/a&gt;, &lt;a href=&quot;https://github.com/GoogleChrome/modern-web-guidance/blob/84ae7251ee919239d5ea85aef25897983f26601e/skills/modern-web-guidance/guides/html/prerendering-custom-elements.md&quot;&gt;pre-rendering&lt;/a&gt;, &lt;a href=&quot;https://github.com/GoogleChrome/modern-web-guidance/blob/84ae7251ee919239d5ea85aef25897983f26601e/skills/modern-web-guidance/guides/html/styling-web-components.md&quot;&gt;styling&lt;/a&gt;, etc. But nowhere does the Modern Web Guidance strongly recommend the agent to use web components – in fact, there’s a whole section titled &lt;a href=&quot;https://github.com/GoogleChrome/modern-web-guidance/blob/b31dc0a43ff5d19bcf386a3476a216f3b39a6f55/skills/modern-web-guidance/guides/html/web-components.md#decide-whether-you-even-need-a-custom-element&quot;&gt;“Decide whether you even need a custom element”&lt;/a&gt; which sounds downright discouraging at times. As written, if you throw the Modern Web Guidance at an agent building a brand-new product, it seems unlikely to me that it would choose to use web components.&lt;/p&gt;&lt;p&gt;To be fair, there is one exception: &lt;a href=&quot;https://github.com/GoogleChrome/modern-web-guidance/blob/b31dc0a43ff5d19bcf386a3476a216f3b39a6f55/skills/chrome-extensions/references/extensions/content-scripts.md?plain=1#L102&quot;&gt;a line for Chrome extension authors&lt;/a&gt; recommends using shadow DOM for complex UI injected into a page. This seems perfectly sensible to me, although it’s a fairly narrow use case. &lt;a href=&quot;https://github.com/GoogleChrome/modern-web-guidance/blob/b31dc0a43ff5d19bcf386a3476a216f3b39a6f55/skills/modern-web-guidance/guides/html/web-components.md?plain=1#L3&quot;&gt;Another line&lt;/a&gt; suggests using web components for “design systems, embeddable widgets, and self-contained UI,” but this is also fairly narrow, and reads to me as a faint nod within the larger context of “decide whether you even need a custom element.”&lt;/p&gt;&lt;h2&gt;Web components at a crossroads&lt;/h2&gt;&lt;p&gt;So where do web components fit into this new AI coding world? I’m not going to rehash all my points about web components’ strengths and weaknesses; I’ve already done that at &lt;a href=&quot;https://nolanlawson.com/2023/08/23/use-web-components-for-what-theyre-good-at/&quot;&gt;considerable&lt;/a&gt; &lt;a href=&quot;https://nolanlawson.com/2024/09/28/web-components-are-okay/&quot;&gt;length&lt;/a&gt;. Instead I want to talk about what’s new if people are no longer writing the code (or increasingly, even reading it).&lt;/p&gt;&lt;p&gt;This section was painful for me to write, because I spent years working on a web-components-based framework (&lt;a href=&quot;https://lwc.dev&quot;&gt;LWC&lt;/a&gt;), participating in the &lt;a href=&quot;https://www.w3.org/community/webcomponents/&quot;&gt;Web Components Community Group&lt;/a&gt; and &lt;a href=&quot;https://github.com/WICG/aom&quot;&gt;Accessibility Object Model group&lt;/a&gt;, and defending web components &lt;a href=&quot;https://nolanlawson.com/category/web-components/&quot;&gt;on my blog&lt;/a&gt;, &lt;a href=&quot;https://podrocket.logrocket.com/what-web-components-are-good-at&quot;&gt;in&lt;/a&gt; &lt;a href=&quot;https://shoptalkshow.com/451/&quot;&gt;podcasts&lt;/a&gt;, etc. And yet I have to acknowledge that their core value proposition have been severely weakened by agentic coding.&lt;/p&gt;&lt;p&gt;In short, web components were designed for a world where people typed HTML by hand, code was scarce, and thus reuse was an economic necessity. None of those things are true anymore, or at least they’re much less true and becoming less so by the day. So the elevator pitch of “build for a common standard and your components will be easier to pick up and reuse” becomes less compelling as more and more people are vibing UIs from scratch on top of a largely invisible platform substrate.&lt;/p&gt;&lt;p&gt;This doesn’t just devastate the value proposition of web components: it also impacts the JavaScript frameworks that inspired them. Increasingly I read about teams &lt;a href=&quot;https://dev.to/playfulprogramming/nobody-argued-for-your-stack-51fj&quot;&gt;rewriting their entire frontend from one framework to another&lt;/a&gt;, based largely on the vibes of “it’s probably better for agents.” Regardless of the merits of these rewrites (which I think ought to be more evidence-based along the lines of “it uses fewer tokens” or “it’s a faster end-user experience”), we’re likely to see more of them in the future. And if people start seeing the framework layer as disposable, it seems unlikely to me that they would assign much value to the layer one step below that.&lt;/p&gt;&lt;p&gt;As I argued in a &lt;a href=&quot;https://nolanlawson.com/2023/12/30/shadow-dom-and-the-problem-of-encapsulation/&quot;&gt;2023 post&lt;/a&gt;, component libraries were already moving from a “batteries-included” model to a more “DIY” mindset. The apotheosis of this is &lt;a href=&quot;https://ui.shadcn.com/&quot;&gt;shadcdn&lt;/a&gt;, which might seem like a machine for spitting out reams of boilerplate, but in a sense, that’s the point. Rather than make your touchpoint with a component system an inflexible API that resists your attempts to style or tweak it, you import the individual bits and pieces and then rearrange them at your will. This shift was already underway before AI coding, and now with LLMs “reams of boilerplate” are an advantage rather than a detriment. And none of this plays to the strengths of shadow DOM, reflected attributes, or other web component mainstays.&lt;/p&gt;&lt;h2&gt;Salvaging web components&lt;/h2&gt;&lt;p&gt;There are two (slightly weak) cases I can try to make for web components in this new world of AI coding.&lt;/p&gt;&lt;p&gt;The first is so-called micro-frontends, or the idea of separating a large UI into multiple sections that can be built by different teams without clobbering each other. Web components were explicitly designed for this scenario: avoiding &lt;a href=&quot;https://bkardell.com/blog/FriendlyFire.html&quot;&gt;“friendly fire”&lt;/a&gt; (in Brian Kardell’s memorable phrasing). In a world of agents, this kind of sandboxing is actually a well-known technique, because typically you want to isolate agents into strict boundaries to avoid them rampaging on top of each other. In other words, web components could theoretically allow you to have multiple swarms of agents working on separate parts of the UI without their CSS, events, or globals clashing with one another.&lt;/p&gt;&lt;p&gt;The obvious counterpoint is that the web already has a great sandboxing primitive, which is iframes. Iframes offer even firmer boundaries than web components: not only are components isolated from each other, but they also live in separate JavaScript realms with &lt;code&gt;postMessage&lt;/code&gt; as the only communication channel. There are several tradeoffs that I don’t want to get into here (synchronous vs asynchronous communication, memory usage, the porousness of closed vs open shadow DOM), but I do think web components have a chance in this fight. (Arguably, the Modern Web Guidance’s “design systems and self-contained UI” are also examples of micro-frontend-like scenarios where web components can shine.)&lt;/p&gt;&lt;p&gt;The second argument is that reuse still matters even when rewrites are just a prompt away. For example, I still believe that my &lt;a href=&quot;https://github.com/nolanlawson/emoji-picker-element/&quot;&gt;&lt;code&gt;&amp;lt;emoji-picker&amp;gt;&lt;/code&gt; element&lt;/a&gt; is a good poster child for an effective web component: there is no reason to rebuild this thing in React, Vue, Svelte, and a dozen other frameworks, even though you could trivially do so with an LLM these days. It’s a standalone, client-only component, and most of its complexity lives in managing the emoji data, IndexedDB, etc., with little need for touchpoints with a framework to manage its rendering or lifecycle. So packaging it as a web component and allowing folks to wrap it in their framework layer of choice (or none at all) is still a sensible distribution model.&lt;/p&gt;&lt;p&gt;Arguing against web components as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Lingua_franca&quot;&gt;&lt;em&gt;lingua franca&lt;/em&gt;&lt;/a&gt; for reuse sounds (to me) like an argument that all code sharing or even open source in general is a waste of time in the agentic era. My colleague André Staltz has shown that this is &lt;a href=&quot;https://socket.dev/blog/ai-has-taken-over-open-source&quot;&gt;clearly false&lt;/a&gt;: if anything, AI coding is increasing the amount of shared code, not decreasing it. Even if you &lt;em&gt;can&lt;/em&gt; rebuild something with agents, that doesn’t mean that it’s worth spending the tokens to do so. (Although I do still wonder about &lt;a href=&quot;https://nolanlawson.com/2025/11/16/the-fate-of-small-open-source/&quot;&gt;smaller projects&lt;/a&gt;.)&lt;/p&gt;&lt;p&gt;The stronger counterargument is that agents already have a perfectly good component reuse layer, which is &lt;a href=&quot;https://youtu.be/P1FLEnKZTAE&quot;&gt;React&lt;/a&gt;. I don’t believe this, though, because I don’t think that React is the last JavaScript framework the world will ever need. Performance benchmarks like the &lt;a href=&quot;https://github.com/krausest/js-framework-benchmark&quot;&gt;js-framework-benchmark&lt;/a&gt; and &lt;a href=&quot;https://github.com/marko-js/isomorphic-ui-benchmarks&quot;&gt;isomorphic SSR benchmark&lt;/a&gt; still stubbornly argue against React adoption: as it turns out, &lt;a href=&quot;https://svelte.dev/blog/virtual-dom-is-pure-overhead&quot;&gt;the virtual DOM is still pure overhead&lt;/a&gt;. React could certainly reinvent itself for the agentic era, but I imagine this could lead to compatibility problems that would argue more strongly for web component adoption, if for no other reason than to get off the update treadmill.&lt;/p&gt;&lt;p&gt;Still, I think the strongest argument of all is that neither web components nor React nor any other framework really matter, except maybe as a footnote in someone’s &lt;code&gt;AGENTS.md&lt;/code&gt; or an aside in an agent’s thinking process. Recently I vibe-coded a small app for my wife, and the agent mentioned that it was wavering between Preact and Svelte before finally settling on Preact. To be honest, I didn’t care at all because the app worked and solved the problem at hand.&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;I still have a soft spot for web components, and when push comes to shove I’ll happily defend them against any detractors.&lt;/p&gt;&lt;p&gt;There’s even a web component on this very site! The theme picker above is an &lt;a href=&quot;https://adactio.com/journal/20618&quot;&gt;“HTML web component”&lt;/a&gt; (or “light DOM component”), which I find quite nice as an alternative to the old-school “HTML with jQuery sprinkles” approach. Defining setup logic in &lt;code&gt;connectedCallback&lt;/code&gt; just &lt;em&gt;feels&lt;/em&gt; cleaner to me than awkward &lt;code&gt;querySelector&lt;/code&gt; acrobatics. That said, I’ll admit that I had to explicitly tell my agent to use a web component (otherwise I’m certain it would have just shrugged and reached for &lt;code&gt;querySelector&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;Despite my sentimentality for web components, though, I think that the web component advocates working on standards, frameworks, or browsers will have to work twice as hard to argue for their relevance in an AI coding future. I no longer have a dog in this fight, but I looked at the status of some longstanding problems with web components and was disappointed to see that &lt;a href=&quot;https://github.com/whatwg/html/issues/10673&quot;&gt;server-side rendering&lt;/a&gt;, &lt;a href=&quot;https://github.com/WICG/webcomponents/issues/909&quot;&gt;stylesheet sharing&lt;/a&gt;, and &lt;a href=&quot;https://chromestatus.com/feature/5188237101891584&quot;&gt;accessibility&lt;/a&gt; still appear to be unsolved. These kinds of flaws – which mind you, directly impact the end-user experience and are thus unchanged with AI coding – will have to be fixed if web components want to have a fighting chance.&lt;/p&gt;&lt;p&gt;If web components don’t survive, or they wither away to forgotten infrastructure on a &lt;a href=&quot;https://chromestatus.com/metrics/feature/timeline/popularity/1689&quot;&gt;minority of websites&lt;/a&gt;, then what will they have accomplished? Well, I do think that one unambiguous victory for web components has been in “explaining the platform.” This was &lt;a href=&quot;https://domenic.me/explaining-away-the-webs-magic/&quot;&gt;one of the original goals of web components&lt;/a&gt;: taking a native HTML element like &lt;code&gt;&amp;lt;video controls&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;/&lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; and explaining how web developers could build it themselves from platform primitives. And in fact if you look at the browser DevTools, you’ll even see “user-agent shadow DOM” hiding inside these elements.&lt;/p&gt;&lt;figure&gt;&lt;a href=&quot;https://nolanlawson.com/media/2026/10/video-with-controls.png&quot;&gt;&lt;img src=&quot;https://nolanlawson.com/_astro/video-with-controls.C2qozcS-_2gUwdh.webp&quot; alt=&quot;An example of Chromium&amp;#39;s DevTools showing a video with controls having a user-agent shadow root. The video is shown on the left and the browser Elements panel in the DevTools on the right, with various elements inside shadow root.&quot; title=&quot;&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;The user agent shadow root for &lt;code&gt;&amp;lt;video controls&amp;gt;&lt;/code&gt; in Chromium DevTools.&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;So from a standards and internal-consistency perspective, web components have been a clear win. They provide a degree of coherence between userland and the platform that, without them, might have felt ad-hoc or inconsistent from browser to browser.&lt;/p&gt;&lt;p&gt;This has also created a symbiotic relationship between standards and userland, where web component concepts have flowed back into standards and influenced the design of new platform features. You can see this most clearly in the &lt;a href=&quot;https://open-ui.org/&quot;&gt;Open UI project&lt;/a&gt;, where terms like “parts” and “slots” are frequently invoked (both of which come from web components), and which has landed several new features in browsers such as &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select&quot;&gt;customizable &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Popover_API&quot;&gt;popovers&lt;/a&gt;, and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API&quot;&gt;invoker commands&lt;/a&gt;, with more likely on the way.&lt;/p&gt;&lt;p&gt;So whatever happens to web components in the future, and regardless of whether web developers ignore them, forget them, celebrate their demise, or write them off entirely, nothing can take this victory away from them. They are woven into the texture of the web platform in a way that can never be undone. For me, this makes me happy even if I never write another web component again.&lt;/p&gt;&lt;p&gt;&lt;em&gt;You can comment on &lt;a href=&quot;https://toot.cafe/@nolan/117470449984835742&quot;&gt;the fediverse&lt;/a&gt; or &lt;a href=&quot;https://lobste.rs/s/dpjkzz/do_web_components_have_future_if_nobody_is&quot;&gt;Lobsters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Cloud computing is a trap, warns GNU founder Richard Stallman | Computing | The Guardian</title>
<link>http://www.theguardian.com/technology/2008/sep/29/cloud.computing.richard.stallman</link>
<enclosure type="image/jpeg" length="0" url="https://i.guim.co.uk/img/static/sys-images/Technology/Pix/pictures/2008/09/29/stallman1.article.jpg?width=1200&amp;height=630&amp;quality=85&amp;auto=format&amp;fit=crop&amp;precrop=40:21,offset-x50,offset-y0&amp;overlay-align=bottom%2Cleft&amp;overlay-width=100p&amp;overlay-base64=L2ltZy9zdGF0aWMvb3ZlcmxheXMvdGctYWdlLTIwMDgucG5n&amp;enable=upscale&amp;s=a5aa8b238387cd6fe46b3d809d40313e"></enclosure>
<guid isPermaLink="false">NyG2LF-MH9v8QKZwc4LSfBvMt29U3Nm0kD9bwg==</guid>
<pubDate>Sat, 17 Oct 2026 05:30:57 +0000</pubDate>
<description>Richard Stallman says web-based programs like Google&#39;s Gmail will force people to buy into locked, proprietary systems that will cost more and more over time</description>
<content:encoded>&lt;p&gt;The concept of using web-based programs like Google&amp;#39;s Gmail is &amp;quot;worse than stupidity&amp;quot;, according to a leading advocate of free software.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.theguardian.com/technology/2008/sep/25/computing.internet&quot;&gt;Cloud computing&lt;/a&gt; – where IT power is delivered over the internet as you need it, rather than drawn from a desktop computer – has gained currency in recent years. Large internet and technology companies including Google, Microsoft and Amazon are pushing forward their plans to deliver information and software over the net.&lt;/p&gt;&lt;p&gt;But Richard Stallman, founder of the Free &lt;a href=&quot;https://www.theguardian.com/technology/software&quot;&gt;Software&lt;/a&gt; Foundation and creator of the computer operating system GNU, said that cloud computing was simply a trap aimed at forcing more people to buy into locked, proprietary systems that would cost them more and more over time.&lt;/p&gt;&lt;p&gt;&amp;quot;It&amp;#39;s stupidity. It&amp;#39;s worse than stupidity: it&amp;#39;s a marketing hype campaign,&amp;quot; he told The Guardian.&lt;/p&gt;&lt;p&gt;&amp;quot;Somebody is saying this is inevitable – and whenever you hear somebody saying that, it&amp;#39;s very likely to be a set of businesses campaigning to make it true.&amp;quot;&lt;/p&gt;&lt;p&gt;The 55-year-old New Yorker said that computer users should be keen to keep their information in their own hands, rather than hand it over to a third party.&lt;/p&gt;&lt;p&gt;His comments echo those made last week by Larry Ellison, the founder of Oracle, who criticised the rash of cloud computing announcements as &amp;quot;fashion-driven&amp;quot; and &amp;quot;complete gibberish&amp;quot;.&lt;/p&gt;&lt;p&gt;&amp;quot;The interesting thing about cloud computing is that we&amp;#39;ve redefined cloud computing to include everything that we already do,&amp;quot; he said. &amp;quot;The computer industry is the only industry that is more fashion-driven than women&amp;#39;s fashion. Maybe I&amp;#39;m an idiot, but I have no idea what anyone is talking about. What is it? It&amp;#39;s complete gibberish. It&amp;#39;s insane. When is this idiocy going to stop?&amp;quot;&lt;/p&gt;&lt;p&gt;The growing number of people storing information on internet-accessible servers rather than on their own machines, has become a core part of the rise of Web 2.0 applications. Millions of people now upload personal data such as emails, photographs and, increasingly, their work, to sites owned by companies such as Google.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.techworld.com/opsys/news/index.cfm?newsid=102279&quot;&gt;Computer manufacturer Dell recently even tried to trademark the term &amp;quot;cloud computing&amp;quot;,&lt;/a&gt; although its application was refused.&lt;/p&gt;&lt;p&gt;But there has been growing concern that &lt;a href=&quot;https://www.theguardian.com/technology/blog/2008/aug/06/whengoogleownsyouyourdata&quot;&gt;mainstream adoption of cloud computing could present a mixture of privacy and ownership issues&lt;/a&gt;, with users potentially being locked out of their own files.&lt;/p&gt;&lt;p&gt;Stallman, who is a staunch privacy advocate, advised users to stay local and stick with their own computers.&lt;/p&gt;&lt;p&gt;&amp;quot;One reason you should not use web applications to do your computing is that you lose control,&amp;quot; he said. &amp;quot;It&amp;#39;s just as bad as using a proprietary program. Do your own computing on your own computer with your copy of a freedom-respecting program. If you use a proprietary program or somebody else&amp;#39;s web server, you&amp;#39;re defenceless. You&amp;#39;re putty in the hands of whoever developed that software.&amp;quot;&lt;/p&gt;</content:encoded>
</item>
</channel>
</rss>
