The brief
My projects were described in three places — the personal site, the business site, and reality — and every new ship meant hand-editing at least two of them. This site is the fix: one canonical registry, edited in one place, that republishes itself.
How it was built
- Projects are database rows. A Supabase
projectstable (public-read RLS) holds every title, blurb, stack list, link, and the case study you're reading right now, as markdown in a column. - The site is static anyway. At build time a script pulls the table, Vite builds the app, and every page — index and details — is server-rendered to plain HTML. Social crawlers (LinkedIn, Discord, Slack) execute no JavaScript, so static HTML is the difference between a rich preview card and a blank one.
- The rebuild is a webhook. A Supabase database webhook fires a Cloudflare Pages deploy hook on any row change. Add a row, and about a minute later the site has republished itself — no rebuild, no redeploy, no git push from me.
- Screenshots are automated. A Playwright script visits each live URL, captures it, uploads to Supabase Storage, and stamps the URL back onto the row.
Stack notes
Vite + React 19 + TypeScript strict, Tailwind v4, shadcn/ui, react-markdown. Cloudflare Pages on the shiner.app umbrella — the front door for everything else that will live there.
