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.

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.

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.

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.

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.