Thoughts
Notes on software engineering, distributed systems, and the future of human productivity.
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 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.
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.
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.
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.
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.
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.
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.
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 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.