Backend Modes

Standalone (Supabase) vs Unified (Soar API): how to choose, how the mode is resolved, and what does not mix.

The template ships with two complete backends behind one set of business protocols. Which one the app is assembled against is a build-level choice made in Secrets.xcconfig — a single install authenticates and stores data against exactly one backend, and there is no user-facing switch.

Standalone ModeUnified Mode
SOAR_BACKEND_MODEsupabase (default)soar_api
AuthSupabase AuthBetter Auth (/api/auth/*, Bearer token)
DataPostgREST + RLSSoar App API (/api/app/v1/*)
StorageSupabase StorageObject storage via presigned upload API
Push testSupabase Edge FunctionPOST /api/app/v1/notifications/test-push
User IDSupabase UUIDBetter Auth text ID (opaque string)
Shares users/data with a web appNoYes — same host as a conforming Web template

Standalone Mode is the classic single-template setup: the iOS app talks directly to your Supabase project. If you only bought the Swift template, this is your mode and nothing about it changed.

Unified Mode points the app at a conforming Web host's Soar App API instead. Web and iOS then share one Better Auth user, one todos table, one profile, and one subscription row — a purchase on either platform unlocks the other. Use it when you run a Web host and Swift as one product.

Start here

Pick the mode, then follow exactly one setup guide:

If you are undecided, the platform-level mode guide and Compatibility Matrix compare the two deployments product-by-product.

How the mode is resolved

SOAR_BACKEND_MODE flows through the normal xcconfig chain into Info.plist, and App/BackendMode.swift resolves it once at startup:

  • soar_api (also accepted: soarapi, soar-api, any casing) → Unified Mode.
  • Anything else — including unset — → Standalone Mode (supabase).

App/BackendFactory.swift is the single place that knows about concrete implementations. It assembles a BackendServices bundle (auth, account, todos, profile, subscription, uploads, device tokens, push test) for the resolved mode; everything above it — AppEnvironment, view models, views — depends only on the business protocols and contains no backend type checks.

No silent fallback. If Unified Mode is selected but SOAR_API_BASE_URL is missing, every request surfaces a diagnosable configuration error ("Soar API backend is selected but SOAR_API_BASE_URL is not set") — the app never quietly degrades to Supabase. A misconfigured backend should be impossible to miss.

The two modes do not mix

Each backend is a separate identity source. A Supabase session cannot call the Soar App API, and a Better Auth session cannot read your Supabase tables — by design there is no bridging, no dual-write, and no fallback from one mode to the other:

  • Auth, data, storage, and subscription always come from the same backend preset. You cannot sign in with Supabase and store todos via the Soar API.
  • Users created in one mode do not exist in the other. The same email registered in both places is two unrelated accounts.

Switching a production app between modes is a data migration, not a config flip. Flipping SOAR_BACKEND_MODE on an install base means: migrating user accounts into the new identity source (users must re-authenticate — password hashes and OAuth links don't transfer automatically), moving todos, profiles, and uploaded files, and re-pointing RevenueCat appUserIDs to the new user IDs. Pick the mode per deployment before launch; treat a later switch as a planned migration project.

On this page