Skip to content

SMACKZ Mobile App

SMACKZ-MOBILE is the customer-facing mobile application for ordering food from SMACKZ restaurants. It is a React Native CLI (bare workflow) app targeting both iOS and Android.

Tech Stack

Component Technology
Framework React Native CLI (bare, not Expo)
Language TypeScript
State Zustand (local state), React Query (server state)
Auth Firebase Phone Auth (@react-native-firebase/auth)
Navigation React Navigation

Authentication

Mobile users authenticate exclusively via phone OTP:

  1. User enters their phone number
  2. Firebase sends an OTP via SMS (or uses a pre-configured test number)
  3. User enters the 6-digit code
  4. Firebase returns an ID token
  5. The app calls POST /auth/login/mobile/:restaurantId with the token
  6. If the user is new, they complete a registration form (first name, last name, optional email)

Test phone numbers bypass real SMS delivery but use the exact same auth flow, so there are no separate "fake login" code paths.

Multi-Restaurant Support

A single phone number can be registered with multiple restaurants. The backend uses base62-encoded Firebase custom claims (m claim) to track restaurant memberships. When a user opens a restaurant's app, the auth flow scopes them to that specific restaurant.

Key Features

  • Phone-based authentication with OTP
  • Restaurant-specific branding and themes
  • Menu browsing with search
  • Cart management with serving size selection
  • Checkout (pickup or delivery, scheduled or ASAP, offer application)
  • Order placement and real-time status tracking
  • Order history
  • Loyalty points and offers
  • Dynamic page rendering (shares logic with web via shared packages)
  • Push notifications via Firebase Cloud Messaging (see Notifications)

Checkout

Checkout integrates order type (pickup / delivery), optional time scheduling, address selection, offer application, and payment.

Flow: CartScreen → CheckoutScreen (modal) with pickup/delivery toggle → conditional PickupScheduler or DeliveryAddressSectionOfferSectionOrderSummary → PLACE ORDER (POST /checkout) → PaymentWebViewScreen. The WebView listens for completed / failed / cancelled postMessages from the payment page.

Dining options are read from the active location (not the restaurant) following the 2026-04 location-scoped settings migration. The canonical key is pickup (the legacy takeAway alias was removed).

Payment URL: ${PAYMENT_URL}/?orderId=...&userId=...&restaurantId=...&token=...&theme=... (Cloudflare Pages, theme light or dark). On success the cart is cleared, checkout state is reset, and the app navigates to the Orders tab.

Component Purpose
OrderTypeToggle Pickup/delivery switch
PickupScheduler Date chips + 30-min time slots
DeliveryAddressSection + AddAddressSheet Address picker + add modal
OfferSection Apply available offer
OrderSummary Live recompute: subtotal − discount + tax + deliveryFee
PaymentWebViewScreen Hosted payment page in a WebView

Hooks: usePickupAvailability(timeZone), useAddresses(), useCreateAddress(), useCheckout(). Store: Zustand checkoutStore (orderType, selectedAddress, selectedOffer, selectedPickupTime, specialInstructions).

See SMACKZ-MOBILE/docs/Checkout-Implementation.md for the full spec.

Build & Release

Environment variables read at build time via react-native-config from .env: APP_ENV, RESTAURANT_ID, FIREBASE_ENV, GOOGLE_MAPS_API_KEY.

Platform Dev Release
iOS npm run ios (simulator), npm run ios -- --device Xcode Archive → Distribute → App Store Connect. Bump CFBundleVersion (every upload) + CFBundleShortVersionString (releases) in Info.plist. Swap GoogleService-Info.plist for the target Firebase env.
Android npm run android ./gradlew assembleRelease (APK) or ./gradlew bundleRelease (AAB for Play Store). Bump versionCode (every upload) + versionName in build.gradle.

Metro: npm start, or npx react-native start --reset-cache after Babel changes.

A scripted release helper exists at scripts/prepare-release.sh — it prompts for platform, bumps versions, clears caches, cleans builds, and reinstalls Pods (iOS) or bundles AAB (Android).

Staging ships as a separate app with bundle IDs smackz-mobile.stg.co.smackz (iOS) and smackzmobile.stg.co.smackz (Android), against Firebase project smackz-platform-staging. Swap Firebase configs and verify Info.plist reversed client ID + GMSApiKey per environment.

Session Management

  • Firebase ID tokens expire after approximately 1 hour
  • On 401 responses, an Axios interceptor refreshes the token via POST /auth/refresh
  • Tokens and user data are persisted in secure storage via Zustand
  • If refresh fails, the user is redirected to the login screen

Branch Convention

Uses qa / staging / main branches. All development commits go to qa.

Key Files

  • SMACKZ-MOBILE/docs/Auth-Implementation.md -- Detailed auth PRD and technical spec
  • SMACKZ-MOBILE/docs/Checkout-Implementation.md -- Checkout flow, hooks, and components
  • SMACKZ-MOBILE/docs/build.md -- Build, environment, and release process
  • docs/Auth-System.md -- Cross-project auth overview