Core Concepts
Understand profiles, startup, routing, state, and API boundaries in the Expo template.
One shared source, two profiles
The CLI generates the same Expo source for both profiles and writes the selection to constants/bowlerkit-profile.ts:
- Account (
account): online runtime with auth, remote preferences, account notifications, and entitlement sync. - Guest (
guest): local-first runtime with no account API calls or remote auth state.
constants/app-mode.ts exposes APP_PROFILE, IS_ACCOUNT_ONLINE, and IS_GUEST_LOCAL. Use these gates when adding profile-specific behavior instead of maintaining a second mobile template.
Startup and routing
app/_layout.tsx initializes i18n, fonts, the auth store, preferences, theme, React Query, monetization, and notification listeners. The root auth listener then routes based on onboarding and authentication state.
Account startup restores the token from expo-secure-store and validates the current user through the useCurrentUser query. Guest startup clears any stale auth token and never hydrates an Account identity. Account-only routes (auth, security, remote help center, and billing) are redirected away in Guest mode.
State ownership
- Zustand stores: auth, preferences, monetization, and security state.
- TanStack React Query: API queries/mutations and cache invalidation.
- Secure Store: the Account bearer token.
- Async/local storage: preferences, onboarding completion, and local UI state.
- Theme context: the active theme registry and brightness.
API boundary
services/api.ts builds URLs as:
EXPO_PUBLIC_API_URL + /api/v1 + endpointSet EXPO_PUBLIC_API_URL to the host root. Account endpoints are protected by a Laravel Sanctum bearer token. Guest requests fail closed with Network requests are disabled for the Guest Local profile.
The Laravel admin panel owns authentication, migrations, uploads, webhooks, and destructive operations. The Go service validates the same Sanctum tokens and serves the protected /api/v1/app/* resource contract.
Add a feature safely
- Decide whether it is shared, Account-only, or Guest-only.
- Put data fetching in a React Query hook and client state in a focused Zustand store.
- Add the endpoint to
services/endpoints.ts; do not duplicate/api/v1in endpoint strings. - Gate Account network work with
IS_GUEST_LOCALor an authenticated queryenabledcondition. - Add a route guard in
app/_layout.tsxwhen a screen must not be reachable in Guest mode.
