Why this one
Buying the web starter and the mobile starter separately leaves you with the hard part: making them agree. Two schemas that drift, two ideas of what a user is, two places a subscription might live. TanBase Universal is both clients built against one Supabase project — same tables, same policies, same profile row.
It is genuinely two codebases: a TanStack Start app and a Flutter app. What's shared is the thing that's expensive to share.
- One schema, one set of policies. Row-level security is written once. A policy that protects a table protects it from both clients, because there is only one table.
- One identity. A person who signs up on the web and then installs the app is the same
auth.usersrow with the same profile — not two accounts you later try to reconcile. - Two billing rails, by necessity. Paddle on the web, RevenueCat in the app. This isn't a shortcut; Apple and Google require in-app purchase for digital goods sold inside an app, and Paddle can't be the merchant of record there. Both rails resolve to the same Supabase row, so your entitlement check is identical wherever it runs.
What you get
Everything in TanBase Web and everything in TanBase Mobile — the full contents of both are listed on their own pages — plus the schema alignment that lets them share a backend.
| Concern | Web | Mobile | Shared |
|---|---|---|---|
| Client | TanStack Start, React 19 | Flutter, iOS + Android | — |
| Auth | Magic link, OAuth | Email, native Google + Apple | One auth.users, one profile |
| Billing | Paddle (merchant of record) | RevenueCat (store IAP) | Entitlement resolved from the same row |
| Data access | Server functions | supabase_flutter | One schema, one set of RLS policies |
| Push / realtime | Supabase Realtime | FCM + Realtime inbox | Same tables |
| Analytics | PostHog + Sentry | Firebase Analytics + Crashlytics | — |
The honest part about "one subscription"
A subscription bought on the web does not automatically unlock the app, and vice versa — not because of how this is built, but because Apple and Google settle their own transactions and Paddle settles yours. What TanBase Universal gives you is the mechanism to make cross-platform entitlement possible: a single entitlements table both rails write into, and one gating helper both clients call. Whether you honour a web purchase inside the app is then your policy decision, and you have the schema to enforce whichever way you choose.
If you only ever plan to sell on one platform, buy that variant instead and keep the $30.
What's not included, on purpose
The union of both variants' gaps: no admin dashboard, no API rate limiting, no CMS, no chat or social feed, no AI integration, and no phone-OTP auth. The web client has no i18n; the mobile client ships EN/ES/AR. The mobile client targets Android and iOS only — no Flutter web or desktop build. Legal screens are structured placeholders on both sides.
Getting it running
Stand up one Supabase project and point both clients at it. Run the web migrations first, then the mobile ones — they're additive and don't collide. Each client keeps its own credential file and its own deploy path: Cloudflare Workers via Wrangler for the web app, the usual store pipelines for the Flutter app.