Philip Sloth Portfolio
The site you're reading — and the live admin dashboard behind it

The portfolio you're looking at right now also has a real-time admin dashboard behind it. The dashboard knows who's on the site within a second of you opening a tab, where every visitor is in the world, what they're reading, and which contact form just landed. Everything is documented here, in plain English, so you can audit how it actually works rather than take my word for it.
This is the site you're reading, and it's also the case study. The portfolio has a real-time admin dashboard behind it, and I've documented how it works below so you can verify the claims I make on the rest of the site instead of taking them on trust. The website itself is built with Next.js, styled with Tailwind, and runs on Cloudflare's global edge network. Every page is pre-built and served as a static file, so it loads anywhere in the world in under a second. All the actual content — projects, blog posts, contact messages, the admin dashboard data — lives in a Postgres database hosted by Supabase. There are two small server programs (Cloudflare Workers) doing the heavy lifting: one handles contact form submissions and emails them to my inbox, the other captures every page view, scroll, and click and feeds them to the dashboard. The most interesting part is the live count of who's currently on the site. When you open a tab, you appear in the dashboard within a second. When you close it, you disappear within a second. If your browser crashes or your wifi drops, a cleanup task runs every 10 seconds and removes any tab that's gone quiet for over a minute. The dashboard also double-checks itself once a second locally, so even if a single live update gets dropped on its way to me, the count never drifts. Whichever way the connection breaks, the number on screen is right within a second. Security is the part most 'full-stack' work quietly skips. Every analytics table is locked down so only logged-in admins can read it. The server programs write data using a special internal key that bypasses these locks, but anyone trying to read from outside — even with the right login — only sees rows they're explicitly allowed to see. The live update channel respects the same rules, so a stranger subscribing from the browser receives nothing. A real example of the discipline that takes: I had a database view that joined contact submissions with the journey of the visitor who sent them, and the Supabase security advisor flagged it as a critical vulnerability. By default in Postgres, views run with the creator's permissions — which would have meant any authenticated user could read every contact form ever submitted, not just admins. I shipped a one-line database fix that flipped it to run with the caller's permissions instead, verified the change actually took effect, and the vulnerability closed. The whole story is in the git history. Browser detection had a similar 'wait, that's wrong' moment. Brave deliberately disguises itself as Chrome to defeat fingerprinting, so server-side detection literally cannot tell the difference. My dashboard had been reporting every Brave user as Chrome. The fix asks the browser directly — Brave exposes a runtime API that returns true if you're using Brave — and falls back through three other detection methods for everything else. The dashboard now correctly identifies Brave, Vivaldi, Edge, Firefox, Opera, and even mobile browsers like Brave on iOS, where every other tracker just gives up. Every database change is tracked as a numbered migration file in git (15 so far) and applied through a small Python script that runs a verification query afterward to confirm the change actually took effect. The whole project is built with safety hooks I share across all my work: automated guardrails that block writes to secrets files, and a gate that won't let me — or any AI agent helping me — declare a task 'done' until the code typechecks and the tests pass. Privacy is built in, not bolted on. The site is genuinely cookieless — visitor and session IDs live in localStorage, never as cookies. There are no third-party trackers, no fingerprinting, no IP storage (Cloudflare resolves location at the edge and only the country and city make it into the database). Browser Do-Not-Track is honoured automatically. A small first-visit banner explains in plain English what's happening, and there's a one-click opt-out toggle on the privacy page for anyone who wants to change their mind later. All data lives in an EU region, raw events are deleted after 30 days, and the privacy page itself reads like an honest README rather than legalese. The kind of posture that should be invisible to a respectful visitor and obvious to anyone who looks for it. I built it this way because I think the developer's job is changing fast. AI can write code faster than any human; what's left for us is judgement — knowing what to build, how the pieces should fit together, where the data flows, and what's missing from code an AI just generated. This site is a working demonstration of that idea.
- Live count of who's on the site, accurate within a second of any tab opening, closing, or crashing — three independent fallback layers
- Detects the actual browser people use — including Brave, which deliberately masquerades as Chrome on the server
- Caught and fixed a critical Supabase security advisor finding (a database view that bypassed access checks) — documented in git
- Database access locked down by row-level security on every table; even the Supabase Realtime channel respects the same rules
- Two Cloudflare Workers handle contact submissions and analytics ingest, with rate limiting and bot filtering
- Cookieless analytics — visitor IDs in localStorage, no IP storage, EU-only data, 30-day raw event TTL, browser DNT honoured
- 15 numbered database migrations applied through a Python script with a verification query for each
- Built with the same automated safety guardrails I use across all my work — no shipping until typecheck and tests pass