Troubleshooting
Symptom-first fixes for the FoodFight client, mobile builds, and local dev. For step-by-step release guides, see Mobile and the linked Frontend pages.
Quick index
| Symptom | Jump to |
|---|---|
npm install / npm start fails | Client build |
lucra-plugin / local package errors | Client build |
| Native app shows old web UI | Capacitor |
| Android signing / AAB fails | Android |
| iOS archive / TestFlight issues | iOS |
| Stuck on loading or wrong login state | Auth |
| API 401 / wrong environment | API & env |
| Deep link / referral / venue not applied | Deep links |
| Stripe / Apple Pay / Google Pay fails | Payments |
| Push not received | Push |
| Customer.io empty / not connected | Customer.io |
| Live fight updates missing | WebSockets |
| Backend won’t start locally | Backend (local) |
| Docs site won’t run | Docs site |
Client build (npm)
Symptom: npm install or npm start fails in client/.
Checks:
- Use a current Node LTS (team standard; re-install deps after switching versions).
- From repo root:
cd client rm -rf node_modules npm install npm start - If the error mentions
lucra-plugin, build the local plugin first (Start here):cd ../lucra-plugin npm install npm run build cd ../client npm install npm start
Symptom: Tests fail with module mocks.
- Client unit tests:
cd client && npm test - See Testing
Capacitor (web + native out of sync)
Symptom: Code changes don’t appear in the iOS/Android app.
Fix: Rebuild web assets and sync native projects:
cd client
npm run build
npx cap sync
Then rebuild/run from Xcode or Android Studio.
Symptom: npx cap open ios / android opens a broken project.
- Run
npx cap syncafter dependency or plugin changes. - Re-open the IDE project under
client/iosorclient/android.
More context: Start here — Capacitor.
Android
| Symptom | What to do |
|---|---|
| Keystore / signing error | upload-keystore.jks is gitignored — get the file and passwords from the team. Expected alias: upload. See Android release. |
| Version code already used | Bump versionCode in client/android/app/build.gradle, rebuild AAB. |
| Changes not in release AAB | npm run build → npx cap sync android → rebuild bundle. |
| Push doesn’t work on Android | google-services.json must exist under client/android/app/. Without it, Gradle skips the Google Services plugin and FCM won’t work. See Push notifications. |
| Play upload rejected | Read Play Console error (target SDK, permissions, signing). Full flow: Android release. |
Command-line AAB (optional):
cd client/android
./gradlew bundleRelease
Output: client/android/app/build/outputs/bundle/release/.
iOS
| Symptom | What to do |
|---|---|
| Archive / signing / provisioning | Use the team’s certs and match profiles; CI path: iOS release (Fastlane). |
| Web changes missing | Same as Capacitor. |
| Apple Pay unavailable | Native build only; set REACT_APP_APPLE_MERCHANT_ID. See Payments. |
| Lucra “bar games” missing | Lucra is iOS-native and gated by feature flags — see client/src/utils/lucraUtils.js. |
We do not rely on a working android_deployment GitHub workflow for store releases; Android is manual per the mobile doc.
Auth and session
Symptom: Blank loading screen forever.
AuthContextwaits forcheckedStorageafter readinglocalStoragekeytokens.- Clear site data / app storage and sign in again if tokens are corrupt.
Symptom: Logged in as wrong user / stale session.
// Browser devtools → Application → Local Storage (or clear app data on device)
localStorage.removeItem('tokens');
Reload the app.
Symptom: Partner dashboard redirects to sign-in.
- Partner routes use
PartnerRoute— user must have partner access in Cognito/backend. - See Routing & auth.
API and environment
Symptom: Calls go to prod while developing (or vice versa).
API hosts are chosen in client/src/utils/env.js and request modules (global/request/*):
- Production:
api.getfoodfight.link,auth.getfoodfight.link - Dev:
api.ff-devs.click,auth.ff-devs.click
Notes:
- Android native is treated as production for env selection.
- Web uses
REACT_APP_ENVand hostname (getfoodfight.link→ prod).
Set REACT_APP_ENV and Stripe keys in client/.env for local web dev.
Symptom: 401 on API calls.
- Token expired — sign out/in;
AuthContextrefreshes via refresh token when possible. - Wrong Bearer token on a manual
fetch— preferglobal/request/request.jshelpers.
See API calls.
Deep links
Symptom: server_code / venue / referral not applied after install.
- Confirm link shape — Deep links.
server_codeis set in Branch.io, not invented in the app.- On native, enable debug:
localStorage.setItem('dlDbgEnabled', '1');Console:
[DLDBG]; trail:localStorage['dlDbgTrail']. - Cold start vs warm: both
BranchDeepLinkHandlerandDeepLinkHandlermust run (mounted inApp.js). - Web fallback:
/openroute (Open.js).
Symptom: Short Branch links don’t resolve.
DeepLinkHandlerfetches*.app.linkURLs; some in-app browsers block redirects — test on device with debug enabled.
Payments (Stripe)
| Symptom | What to do |
|---|---|
| Stripe Elements won’t load | Check REACT_APP_STRIPE_TEST_KEY / REACT_APP_STRIPE_LIVE_KEY in .env; key selection in utils/env.js. |
| Apple Pay not offered | Native iOS only; REACT_APP_APPLE_MERCHANT_ID set; Stripe.isApplePayAvailable() true. |
| Google Pay not offered | Native Android only; Stripe.isGooglePayAvailable() true. |
| Payment succeeds but fight/reservation fails | Backend must receive payment_intent.id after confirm — see fight PaymentStep / reservation checkout logs. |
Full flow: Payments.
Push notifications
| Symptom | What to do |
|---|---|
| No permission prompt | Push requires a native build; not supported in browser-only npm start. |
| Token never reaches backend | After grant, PushNotifications hook calls addDevice → PUT user/add_device. Check network tab / logs. |
| Android: no FCM | Missing google-services.json — see Push notifications. |
Customer.io
| Symptom | What to do |
|---|---|
Customer.io analytics not available | Init failed — check console from customerio-init.js; REACT_APP_CUSTOMERIO_API_KEY set. |
| Dashboard shows “not connected” on localhost | Expected — CIO often needs a public URL; test on staging/prod. |
| Events missing | User must be identify’d (sign-in/sign-up); check identify before custom trackEvent. |
| In-app messages never show | Gist is disabled in code today (loadGist() returns false). |
| Server-side events | Bet resolution and webhooks use backend libs/customerio — not covered by the frontend doc alone. |
See Customer.io.
WebSockets (live fights)
Symptom: Profile fight status doesn’t update in real time.
- WebSocket is built in
components/websocket/WebSocketClient.jsand used fromProfile.js. - Requires valid
userId+ auth token; URL is built from env (wss in prod). - http site with wss URL can warn in console — test on matching scheme or native app.
See WebSockets. Historical design: App WebSockets (contributing).
Backend (local)
Symptom: Service won’t start or tests fail.
cd backend
make help
Common services: make user-service, make restaurant-service, make partner-dashboard-service, make down.
Symptom: Customer.io-related component tests need mock CIO.
- Docker Compose profile
customerio/wiremock_customerio— seebackend/compose.yamlandMakefiletargets that include--profile customerio.
Component / BDD tests: Local Tests.
Docs site
Symptom: make run fails in docs/.
cd docs
bundle install # first time
make run
Site config: docs/_config.yml (Just the Docs). Published: foodfightv2.pages.dev.
Symptom: <link> placeholder broken after adding a page.
- The docs do not support Jekyll/Just-the-Docs-style
<link ...>placeholders or Liquid tags in our current tooling. - Use normal relative links like
[Start here](./start-here.md)or a placeholder like<link>if you’re writing a stub.
Still stuck?
- Note platform (web / iOS / Android) and environment (local / dev / prod).
- Capture console + network errors (Sentry may already have them — Sentry).
- Check the feature map for which module owns the flow: Frontend overview.