Spent the last few months building a small free platform of dev tools as a solo side project. The wedge product is an AI code-roaster — paste a snippet, it roasts it for fun, then drops the comedy and walks through the actual issues it found. The rest of the platform (calculators, quizzes, debug challenges, a CSS battle, a small forum) sits behind it but the roaster is the only thing people share, so it's the one I want to talk about.
Posting here mostly because the technical decisions might be useful to anyone trying to ship a content-heavy SPA without going to Next or paying for SSR.
Stack
React 18 with Vite 5, TypeScript, Tailwind. Supabase for Postgres, auth, storage and edge functions. Gemini 2.5 Flash for the AI calls (significantly cheaper than the OpenAI equivalent at this volume). Stripe for payments via webhook into an edge function. Hosting and DB on free tiers, only meaningful cost is the AI API and it's in single-digit dollars per month.
The part I'm proud of: SEO on a Vite SPA without SSR
Googlebot kept timing out on hydration so the long-tail pages weren't getting indexed. Instead of moving to Next or paying for prerender.io I wrote a dual pre-rendering layer:
<noscript> block that contains the critical content of each route in the user's locale, injected at build time.#seo-prerender div that holds the same content for crawlers that execute JS but bail before full hydration.About 40 lines of code total, no SSR runtime, no extra service. Indexed pages went from a few hundred to tens of thousands over about ten weeks once Googlebot started trusting the pages.
Edge functions kept tiny
All edge functions use native crypto.subtle instead of pulling in Deno crypto deps. Bundle stays small, cold starts measured under 100ms on Supabase's runtime. Worth doing — the difference between a 50KB and a 500KB function bundle is brutal on cold start latency.
The user has developed an AI code-roaster tool as part of a free platform of dev tools. They share technical insights about building a content-heavy SPA using Vite without SSR, focusing on SEO strategies, edge function optimization, and atomic operations in Postgres. They seek feedback on their pre-rendering approach, edge function bundle size, and potential performance improvements.
Atomic operations in Postgres, not the app
Forum votes and showcase upvotes go through Postgres functions with row locks (toggle_forum_vote, toggle_upvote). Race conditions can't double-count, and I don't need to think about it in the client. This is one of those "do it once, never debug it again" patterns I wish I'd used from day one.
Subscription gating at the DOM level
Premium features aren't hidden with CSS — they're removed from the DOM entirely by a SubscriptionGate wrapper. DevTools can't reveal them because they're not there. Sounds obvious in hindsight but I see plenty of paywalls that just toggle display: none.
Performance numbers (measured on the homepage, mobile 4G profile)
What I'd love feedback on
Not asking anyone to use the thing, just genuinely curious if the technical choices hold up under scrutiny.