Thoughts

Notes on software engineering, distributed systems, and the future of human productivity.

Giving an Inbox to Each Agent

Password resets, invoices, and support replies still arrive by email, and my agents live on HTTP. Mailingest is the Rust mail platform I built so that an inbox costs one API call: an address whose mail shows up as a signed webhook.

Building a Better WhatsApp SDK

whatsapp-web.js runs a whole headless Chromium to act like a phone. The other door skips the browser and speaks WhatsApp's native protocol over a plain WebSocket, then hands you a raw socket and a firehose of events. whatsweb is the thin layer I built to make that socket feel like a bot.

The Distance From a Message to Your Code

The same bot, a user's message answered by code I wrote, costs a handful of lines on Telegram, a gateway and a bag of intents on Discord, and a whole headless browser pretending to be a phone on WhatsApp. Four libraries in, the pattern was clear, and the hard part was never the bot.

A Kernel Per Bad Idea

My agents write code nobody reads, and then they want to run it. So I built the place it runs: a Firecracker microVM per execution on a box I own, where the boundary is a guest kernel rather than a promise the model makes.

A Wrapper Is a Bug Report

My API has fifteen repository files that are the same file, and thirty `as any` casts in the data layer of an ORM sold on type safety. Better Drizzle exists because everyone writes that layer by hand. I think it belongs in Drizzle itself, and the bug I found while checking makes the case better than I wanted it to.

A Server That Bills Like a Function

Fluid compute makes a long-lived server bill like a function: it stops charging you for the I/O wait that classic serverless bills in full. That part is not virtualization magic, it's a worker pool and one counter in cgroups v2. I checked what I could rebuild on the same Hetzner box I run everything on, and where the box says no.

When the Vectors Live in a Bucket

Object storage is the cheapest durable bytes you can buy and the worst place to search a million vectors. I forked VecPuff and taught its index to keep one bit per dimension resident, so a query pulls a full vector from S3 only when the cheap guess is too close to call.

A URL That Speaks Markdown

The article you are reading is also a plain-markdown file, a .md away. This is the content negotiation that serves the same writing to people and to machines from one source, and why it matters now that some of your readers are not people.

The Bots That Almost Match

Exact-match blocklists are blind to a bot farm that mutates its fingerprint by one field per request. This is how MinHash and locality-sensitive hashing turn "have I seen this exact client" into "have I seen something shaped like this", and catch the farm in sublinear time.

Everything Around the Charge

The request that takes a payment is four lines. Everything that makes it safe to build a business on, so a retry never double-charges and a dropped webhook never loses an order, is the actual work. How I shaped Paybit's crypto payments API on the pattern Stripe proved.

A Payment Gateway That Never Touches the Money

A payment processor is, by definition, the thing that holds your money for a moment. Paybit is my attempt to delete that moment: a non-custodial crypto gateway that splits every payment on-chain, and for Bitcoin watches your own wallet instead of holding a key.

Sealed in Plain Sight

A price on a page is a fact someone paid to produce, sitting in public for anything to copy. I'm building my own anti-bot seal to change what that copy costs, and this is how it works.

A Reaction Bar That Remembers You Without Knowing You

An emoji reaction bar with no login has a trust problem, because a number anyone can click is a number anyone can lie to. Here is how mine counts clicks from strangers and still believes the total, using two disposable identities instead of an account, a write that can only move your own row, debounced optimistic updates, and a Redis-fanned SSE stream that makes every open tab react at once.

How to Build Your Own Vercel (Self-Hosted PaaS on a VPS)

A control-plane and data-plane tour of how a modern PaaS turns a git push into an immutable deployment, from the static-versus-server split to serverless cold starts and Vercel's Fluid compute, then an honest map of how to rebuild the same machine on a VPS you own.

How a Website Decides You're a Bot

A defender's-eye tour of how modern anti-bot systems actually work in 2026, from passive TLS and HTTP fingerprints to an obfuscated client that probes your browser, server-side ML scoring, and tokens that expire in seconds. Plus an honest split of what a small team can build and what it has to rent.

A Film as a Column of Color

The third generative-art engine in the series. The problem of turning a seed into something that reads like a film reduced to color, a little of the maths behind it (seeded noise, OKLCH, a texture model), and a demo you can drive.

More Backend Than a Blog Needs

How pablofr.com is actually built. Three services, a shared data-stack of Postgres, Meilisearch and Redis, one real work queue, and a lot of SSE. Why a personal site is over-engineered on purpose, and where that pays off.

Marking Media So Leaks Have a Name

How I'm building Protomarc, a system that marks images, video, audio, and PDF so a file can prove who owns it and, if it leaks, point back to whoever it was given to. A high-level look at the problem and the hard parts.

How I Turned a VPS into a Platform

A design decision, not a demo. Why I encoded a whole VPS as one Go CLI, pfrctl, instead of renting a PaaS or carrying a heavy self-hosted panel, and where that trade-off pays off.

Avatars from a Username

A follow-up to the Vasarely piece. How I generate deterministic avatars from a username, first as ordered-dithered identicons, then as halftone dot fields where the dot size does the drawing.

Generating Vasarely in Code

How I rebuilt Victor Vasarely's Vega-Nor as a pure, deterministic TypeScript function, with OKLab paint ramps, an area-conserving spherical warp, and colorways generated from a seed. Every image here comes from a seed.

Understanding React Server Components

How React Server Components split an app across the server/client boundary, why they never hydrate, and the composition pattern for putting server content inside a client component.

Getting Started with Next.js 16

What actually changed in Next.js 16, from the "use cache" directive to Turbopack as the default bundler, the React Compiler on by default, proxy.ts in place of middleware, and native View Transitions.

Building APIs with Hono

How I build type-safe APIs with Hono: the router, the Context object, Zod validation, centralized error handling, and end-to-end types shared with the frontend.