[ build_log ]

How?

The full stack behind a personal site running on a $4 microcontroller – explained.

[ architecture ]
Architecture Diagram
[ the_breakdown ]

The core idea is simple get maximum out of a $4 piece of silicon and 520KB of RAM by leveraging bindings, much like you would in a Cloudflare environment.

It all started while I was studying about Durable Objects. I found the concept incredibly cool. While reading the docs, I noticed an ESP32 sitting on my desk collecting dust. Since I already run a homelab, I wanted the ESP to serve content to the internet just like my main server does. The catch? An ESP32 can't run cloudflared, and there was no way I was going to expose my home network to the open web. So, I came up with this...

But first, let's take a step back and understand standard serverless Workers. By design, they are entirely ephemeral. They spin up at the edge, run your code, and die. If you try to save state in a global object like an active connection to an ESP32 or a live counter it gets wiped out between requests. Every new user hitting your API might trigger a completely fresh instance of your code.

That's exactly what Durable Objects solve. They bring state to the edge. A Durable Object guarantees that only one single instance of itself exists globally at any given time. Because it doesn't just spin up and die, it can keep data in its memory, maintain long-lived WebSocket connections, and act as a reliable, persistent middleman between the open internet and my local hardware.

Now back to topic... An HTTP request comes in from your browser and hits a Cloudflare Worker. Because we are using a Durable Object to maintain that globally active WebSocket connection, the Worker can simply grab that connection and forward the request directly to the microcontroller.

Once the request reaches the board, the ESP32 fetches the pre-built web assets from a 1.5MB LittleFS partition on its internal flash. It chunks the data, streams it back over the WebSocket, and Cloudflare delivers it seamlessly to you.

And that's it. You got yourself a tiny, low-power, and globally distributed web server.

[ extra_cycle_use ]Because the web server barely breaks a sweat, I realized I was wasting half of the ESP32's dual-core architecture. To fix that, I decided to pin a Duino-Coin miner to the second core. It's a work in progress, but depending on when you are reading this, it might already be running and stacking up DUCO.