← titouanguerin.com / colophon
how this site runs
I did not want to pay for a server, so the site is hosted on my Raspberry Pi 5 sitting on my desk, and briefly explain here how.
## why a pi
This kind of portoflio website doesn't get thousands or millions of visitors per day (for now?), therefore a Pi 5 can easily handle it. The device only draws a few watts, so hosting at home costs less than a coffee a month, and much less than if I had to pay for a server provider. The one catch of this setup is that a home connection sits behind a router with no fixed address and no ports I want to open. A Cloudflare tunnel solves exactly that: the Pi dials out, Cloudflare holds the public address, and nothing on my network is reachable directly. I also get to play around with this awesome toy, which is always fun. The Pi does a few other things for me at home too, like a little self-hosted drive for my photos and videos, and I'll probably write a page about that setup eventually.
## the stack
- Next.js and TypeScript for the pages, rendered on the server so the site is plain HTML to a crawler and works (mostly) with JavaScript off.
- Tailwind for the styling, and it's a bit better than vanilla CSS from my experience.
- FastAPI in Python for the little backend: the live stats in the footer, the visitor counter, and a cache in front of GitHub, OpenAlex and Cloudflare so the page never depends on them being up.
- Cloudflare for DNS, TLS and the tunnel, and systemd keeps the three services running through reboots on my Pi.
## things i like about it
- The footer is live. CPU, memory, disk and uptime come from the Pi every 5 seconds.
- Deploys cannot half-break it. A script builds the new version into a scratch folder, swaps it in only if the build succeeded, restarts, checks that the page now carries the new commit hash, and rolls back on its own if it does not. It has done that once, for real.
- The visitor counter cannot track you. It stores a hash of your address mixed with the date and a secret that never leaves the Pi. Same person tomorrow, different hash. No cookies, nothing to join.
- Nothing loads from anyone else. The only JavaScript on the page is my own, about 110 kB of it, used for small things like the dropdown menu and the light/dark switch. There is no external analytics script adding more, and the single embed is the YouTube video of my RL agent in the Dark Souls III project, which only loads when you open that row. I tried to keep it as light as I could.