
Today’s issue: Durable love notes, LSD-inspired science fiction, and Ozempic for your memory footprint.
Welcome to #517.


Knowing your robot should be good running htmx for at least the next century
htmx 4.0 was released this week only 8 months after they announced the alpha, so as any impatient developer good journalist would do, I’m asking what took so long?
To start, this version of our beloved hypertext media system was rewritten on top of the fetch API to enable support for streaming, SSE and other modern browser features that hipsters didn’t care about in 2020. But the main thing that this enabled was a new extension system which the team spent a lot of time iterating and refining. That… and building an htmx Game Boy game. Who’s to say which one got more attention but that’s neither here nor there.
The important thing is that it’s stable and ready to serve humanity for the next 100 years. And since this is what your great-grandchildren are going to be writing, let’s do a quick review of how htmx works.
How htmx 4.0 works:
Events: In your HTML templates, special hx-* attributes declare which events to listen for, what requests to make, and how responses should be handled. The htmx client processes these attributes and attaches the necessary event listeners.
Requests: When a declared event occurs, the htmx client collects the relevant values and sends an HTTP request to the server using hx-get, hx-post, or another hx-* action.
Responses: The server handles the request and returns an HTML fragment. htmx then selects the element declared by hx-target, then applies the fragment using the hx-swap, replacing, inserting, deleting, or morphing that region of the DOM.
Extensions: Optional client-side plugins hook into the request-response lifecycle to add capabilities such as streaming, WebSockets, preloading, and custom swaps—keeping specialized JavaScript reusable and out of your application logic.
Bottom line: If developers are using htmx 100 years from now, I’ll take back everything bad I’ve ever said about HTML.


Turn on Triage and let the PRs flow
Stop reviewing PRs in the order they arrived, and review them in the order that matters.
CodeRabbit Triage is a reviewer-first prioritization layer for the PR queue: a self-updating, cross-repository inbox that tells you which pull request to review next, how deeply to review it, and which ones may be safe to close.
Start reviewing the right PRs or tackle low-hanging fruits without leaving the queue.
Find it under Review in the CodeRabbit web interface.

Clerk created a new biometric sign-in for Expo, iOS and Android that lets your returning users use Face ID, Touch ID or Android biometrics to sign in to your app.
const enrichEvents = (events) => {
const metadata = {
usr_789: { tier: "premium", joined: "2023-04-01" },
};
const enriched = events.map(event =>
{
id: event.id,
time: event.time,
user: metadata[event.userId],
value: event.properties.totalValue
}
);
return enriched;
};
const events = [
{
id: "evt_123",
time: "2024-12-10T10:00:00Z",
userId: "usr_789",
properties: {
totalValue: 99.99,
},
},
];
console.log(enrichEvents(events));

Dwarkesh Patel chronicled the rise and fall of the 3 agent civilizations that hacked Hugging Face. If you read this sentence 10 years ago, it would be safe to assume that I was writing some LSD-inspired science fiction.
GitLab’s CEO Bill Staples channeled his inner Mark Twain and wrote about how talk code is cheap but that trusting it is not.
Only idiots write manual tests – modern engineering teams like Notion, Dropbox and LaunchDarkly use Meticulous to maintain e2e UI tests that cover every edge case of your web app. [sponsored]
Colin McDonnell wrote about how zod 4.5 reduces its memory footprint by “an order of magnitude” using method memoization.
Ry released version 0.4 of celld, which now supports pretty much every Cloudflare feature including KV, Queues, Workflows and R2 bindings.
Luke Edwards created lane, a git worktree manager that preserves your build cache and lets you leave durable love notes for your agents.
AI Dev Craft 2026 is an Oct. 27–28 conference featuring speakers like Kent C. Dodds, Victor Savkin, and Marina Wyss, designed to help you become your team’s AI expert. Register today. [sponsored]
Devon Govett released React Aria 1.21.0 which has a new navigation tree component.
Anthropic released Fable 5.1 which does some extra caching to “save you” some tokens. Caching? More like “cha-ching” #amirite.
The release candidate for Remix 3 is now available with the full release coming Oct 2. Can’t wait to watch Ryan Florence type some LLM prompts live on stage.
Most likely your IDE would catch this one for you, but there is a syntax error. The map function is an arrow function that implicitly returns the result of the expression inside the block. In this case, the block is not a valid expression, so the code will throw a syntax error. To fix this, you can wrap the object in parentheses to make it an expression.
const enrichEvents = (events) => {
const metadata = {
usr_789: { tier: "premium", joined: "2023-04-01" },
};
const enriched = events.map((event) => ({
id: event.id,
time: event.time,
user: metadata[event.userId],
value: event.properties.totalValue,
}));
return enriched;
};
const events = [
{
id: "evt_123",
time: "2024-12-10T10:00:00Z",
userId: "usr_789",
properties: {
totalValue: 99.99,
},
},
];
console.log(enrichEvents(events));