BowlerKitBowlerKit
Features

Core Concepts

10/11/2026

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 + endpoint

Set 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

  1. Decide whether it is shared, Account-only, or Guest-only.
  2. Put data fetching in a React Query hook and client state in a focused Zustand store.
  3. Add the endpoint to services/endpoints.ts; do not duplicate /api/v1 in endpoint strings.
  4. Gate Account network work with IS_GUEST_LOCAL or an authenticated query enabled condition.
  5. Add a route guard in app/_layout.tsx when a screen must not be reachable in Guest mode.