For tenant isolation, I’d make the tenant ID part of every server-side data access path rather than relying on the page-level route alone. It’s easy for a later query to accidentally bypass the route assumption.
For a student project, I’d try Netlify for the Next app and Supabase’s free Postgres tier. It keeps hosting and the database separate, and both have enough room for learning without paying upfront.
The embed subdomain + stricter main-app CSP is a good call. I’d mainly watch the middleware path over time: keep the embed rules tiny and covered by tests, because frame-ancestors bugs are the kind you only notice after people start embedding it.
For cost cutting I’d look at Cloudflare first. Workers/Pages + D1/R2/KV/queues covers a lot, and if you want a proper backend shape use Hono instead of plain server routes. Feels closer to Express, but fits the edge/runtime model better. Just check Node/TCP compatibility before moving everything.
Yep. The part I’d add is that “runs outside Vercel” and “matches every Vercel convenience” are different claims. Basic SSR/API routes are straightforward on a normal Node host. The things to check deliberately are image optimization, ISR/cache behavior, edge runtime assumptions, preview deploy flow, and how environment variables/secrets are managed across branches.
Linting helps, but I would not rely on ESLint alone for Supabase boundary bugs. Add small wrappers around reads/writes, make server/client usage explicit, and test the auth/session edge cases. Static checks are strongest when the architecture gives them simple rules to enforce.
I would decide by workload first, not brand. Your Next app, Supabase, Python automations, Stripe webhooks, and AI calls have different failure modes. For launch, I’d choose the setup with the fewest moving parts, good logs, easy rollback, and predictable webhook/background-job behavior. You can optimize provider cost after real usage appears.
I would trust database-enforced tenant isolation more than app-layer filters, but only with a few guardrails around it. FORCE RLS is a good default because it removes the "someone forgot the where tenant_id = ..." class of bug. Before using it in a real B2B SaaS, I would check: - integration tests that try cross-tenant SELECT/UPDATE/DELETE on every tenant-scoped table - migration checks that fail if a new tenant table ships without RLS enabled - no request path ever gets the Supabase service-role key - background jobs and webhooks set tenant context intentionally, not implicitly - SECURITY DEFINER functions/triggers are reviewed very carefully - audit logs include actor, tenant, request id, and the thing that changed So yes, I like the direction. I just would not treat RLS as the whole permission system. App code should still decide roles/actions; the DB layer should be the last line of defense that prevents one missed filter from becoming a data leak.