The Contrast Is the Point

What Five Timelines Teach Us About Software, Trends, and the Nature of Change

⚛️

React

The constantly reinventing library. Class components → functions → hooks → server components → compiler. What's "best practice" today is legacy tomorrow.

13 years, 7 paradigm shifts
🔗

HTMX

The quiet hypermedia revolution. From a jQuery plugin in 2013 to 72.9% admired in 2024. It didn't reinvent anything — it asked what if we just used HTML properly?

13 years, 1 idea done right
🐹

Go

The boring language that runs the cloud. Ships every 6 months on a strict cadence. One promise: if it compiles today, it compiles tomorrow.

17 years, 1 compatibility promise
🦀

Rust

The language that replaced C++ where failure is unacceptable. The borrow checker says "no" at compile time so production never says "no" at runtime.

20 years, 1 borrow checker
💚

Node.js

The JavaScript runtime that put JS on the server. Forked, reunited, and now competing with Go and Rust for the same workloads. The incumbent everyone is trying to unseat.

17 years, 3 billion npm downloads/week

Decades of "Best Practice" — A Visual Comparison

React
createClass → ES6 → functions → hooks → concurrent → server → compiler
HTMX
intercooler.js → htmx 1.0 → htmx 2.0 → htmx 4.0
Go
Go 1.0 → modules → generics → slog → iterators → Swiss Tables
Rust
Rust 0.1 → 1.0 → editions → async/await → Linux kernel → 2024 edition
Node.js
npm → Express → io.js fork → v4.0 → test runner → permission model → SEA
200620102014201820222026
"There is no set-in-stone way to build software. What's 'best practice' today is legacy tomorrow. The only constant is change — and the wisdom to know when to embrace it, and when to resist it."
— The thesis of five timelines

1 Complexity Is Not Inevitable

React's journey from class components to server components shows that complexity can spiral — but it's not the only path. htmx and Go prove that simplicity scales. The question isn't "how do we add features?" but "do we need them?"

2 The Pendulum Always Swings

The web went from server-rendered HTML → SPAs → server components → hypermedia. Go went from "too simple" to "runs the cloud." Rust went from "too hard" to "replacing C++ everywhere." Every pendulum swing creates winners and losers. The smartest move is understanding the swing, not fighting it.

3 Stability Is a Superpower

Go's compatibility promise, Rust's edition system, and React's constant reinvention are opposite strategies — all successful. Go's 13-year backward compatibility means a 2019 program still compiles in 2026. Rust's editions let the language evolve without breaking existing code. Stability has compounding value.

4 The Right Tool Depends on the Job

React for rich client-side UIs. HTMX for server-rendered simplicity. Go for cloud infrastructure. Rust for systems where failure is unacceptable. Node.js as the universal runtime layer. None of these timelines is "right" — they're right for different problems. The best engineers know all five stories and choose accordingly.

5 Incumbents Get Challenged

Node.js dominated server-side JavaScript for a decade. Then Go started compiling TypeScript 7.0, Rust rewrote the JS toolchain (Vite, Rolldown, Oxc), and Deno/Bun emerged as faster alternatives. Being the default doesn't mean staying the default. Node survived by absorbing ideas from its competitors — built-in test runner, permission model, single executables. The lesson: innovate or get innovated on.

The Five Lessons

React teaches us that innovation is relentless. In 13 years, it went from createClass to an auto-memoizing compiler. Each shift was once "the future." The community now questions the SPA paradigm itself. React's lesson: the pace of change is real, and ignoring it carries a cost.

HTMX teaches us that the answer is sometimes "go back." After a decade of SPAs, state managers, and bundlers, Carson Gross asked a simple question: what if we just used HTML? The answer resonated with thousands of developers. HTMX's lesson: the web was designed as a hypermedia system — maybe we should use it that way.

Go teaches us that boring is a feature. Six-month releases. Backward compatibility since 2012. No breaking changes, no hype cycles, no viral tweets. Just a language that compiles fast, runs fast, and keeps working. Go's lesson: the best technology is the one you don't have to think about.

Rust teaches us that the hardest problems are worth solving. Memory safety without a garbage collector. Zero-cost abstractions. A borrow checker that rejects your code at compile time so production never rejects you at runtime. Rust's lesson: the compiler is the strictest code reviewer you'll ever have — and it's free.

Node.js teaches us that incumbents must innovate or die. Dominant for a decade, then Go started compiling its successor's language, Rust rewrote its toolchain, and Bun/Deno shipped faster runtimes. Node responded: built-in test runner, permission model, single executables, new release cadence. Node's lesson: being the default is temporary — the only way to stay is to keep earning it.

The contrast is the point.
There is no single "right way" to build software.
There are only trade-offs, context, and the wisdom to choose well — and the humility to know when the ground is shifting beneath you.