How RiftSeed is built: the stack, the method, and how I work with AI
· 10 min · riftseed, agentic-coding, supabase, cloudflare
One engineer, a shared foundation, and real apps built with AI agents under human review. What’s underneath, and how I actually work on it.
RiftSeed isn’t a product, it’s my workshop. A place where I take apps from idea to production using AI to write the bulk of the code, and keeping the human (me) at the point where things get decided. I started to understand one thing: how far a single person can get today, with these tools, if they accept the discipline it takes not to hurt themselves. This piece is what’s under the hood.
The stack, briefly
Frontend Vite + React + TypeScript, served static from Cloudflare Pages. Backend Supabase: Postgres with row-level security everywhere, Deno Edge Functions for the sensitive logic, pg_cron for periodic jobs, Auth for anonymous and registered users, Storage. No server of mine to keep alive. The AI features go through OpenRouter, so I swap models without touching the product.
The choice that matters most is the least visible: apps don’t start from scratch, they’re born inside the same architecture and inherit what already exists: accounts and access, notifications, telemetry, themes, AI spend caps, row-level security. A new app’s first prototype starts with half the foundations already standing. It’s why I can keep up with several things on my own.
How I work with agents (the method, not the magic)
The code is written largely by AI agents, with me acting as the comparator. It isn’t “give a prompt and hope”. A serious task starts from framing: what it has to do, what the real constraints are, what it must not break. Then the agent implements against that spec, tests run alongside, and I read the result: not every line, the behaviour. Two exits: forward, or back to the agent with notes. The error comes back as an instruction, not a hand-patch of mine.
On big tasks I don’t use a single agent. I split it: a planner, an implementer, a verifier; or a panel of different perspectives that critique each other before I decide. It’s slower than one shot, but it catches the holes one shot misses. On prompts I stopped early looking for the magic phrase: what matters is the structure around it: the spec, tests as a gate, the fact that every change is extractable and reversible. Mastery of the tools matters more than the perfect sentence.
RLS everywhere, and the bug that taught me to respect it
All data is protected by row-level security at the database level, and sensitive writes go only through edge functions that defend themselves: rate limits, whitelists, checks before the model. One day a function was returning empty data intermittently and I couldn’t see why. It was auth.uid() returning NULL under an anonymous session, in a spot where I assumed a user existed. Not a crash: a silence. Hence the rule I carry around: under RLS, “no error” doesn’t mean “all good”, it means “check what this role actually sees”.
AI inside the product, not just in the workshop
There’s AI in the way I build, and AI inside the things I build. Each AI feature has its own model slot, with a fallback chain: if the preferred model is down or too pricey, it drops to a cheaper one instead of breaking in the user’s face. Each app has an AI spend budget: a daily cap and a rate limit counted before calling the model, so a rejected request doesn’t burn budget. The site chatbot is the most visible experiment: it answers from a curated knowledge base, within strict rules on what it can and can’t say.
A detail that bit me: a tool-call that ranked some results was reading a value frozen at fetch time instead of at the current hour. It answered with slightly wrong rankings without ever being obviously wrong. I learned to distrust errors that don’t shout.
Feedback, telemetry, and respect for whoever’s looking
The loop doesn’t close at release. Comments from the people using the apps are collected and classified by AI into change requests with a first impact analysis; then the AI and I weigh what really matters and I decide what enters the next round. To understand what gets used I record my own telemetry, no third-party tools: essential events, a random session id, the country inferred from the network infrastructure without storing the IP, ninety-day retention. No profiling, no external trackers. It’s the most respectful system I knew how to build, and also the easiest to explain.
What I want to try next
No grand claims: what I care to measure is how the distance between an idea and something you can try keeps shrinking with each model generation, and where it stops shrinking. The shared foundation grows by sedimentation (a module, a test, a piece of framework at a time) and each new project should start further ahead than the last. If one day one of these apps genuinely earns it (a real user who cares), the next step is graduation: its own domain, a separate project, and the boring-but-serious part that isn’t there today. For now it stays an “if”, not a plan.
Why in the open
I keep it all here, with the honest status of everything, for a practical reason: building this way is also a way to learn the tools deeply: how agents hold up on a real problem, where they break, how much a prototype actually costs today versus a year ago. The distance between an idea and something you can try has shrunk a lot. Not because AI does it all on its own (it doesn’t) but because one person with a method and a shared foundation gets where a small team used to be needed. The rest I find out by building, and when I break something I write it down.