The React Native mobile application for The Wunderkind Factory, a football club management strategy game. Contains the core game loop, the dynamic 8-trait Personality Matrix engine, and offline-first synchronisation logic.
| Layer | Technology |
|---|---|
| Framework | Expo SDK 54 (managed workflow, Expo Go compatible) |
| Navigation | Expo Router v4 (file-based) |
| State | Zustand + AsyncStorage (persist middleware) |
| API / Sync | TanStack Query v5 (offline mutations) |
| Styling | NativeWind v4 (Tailwind CSS for React Native) |
| Icons | Lucide React Native / Custom SVG Pixel Art |
| Font | Press Start 2P (pixel art aesthetic) |
The app is client-authoritative to support seamless offline play:
- GameLoop (
src/engine/GameLoop.ts) — processes the Weekly Tick entirely on-device: trait shifts, financial deductions, behavioral incidents. - AsyncStorage persistence — Zustand stores are persisted via
@react-native-async-storage/async-storageso state survives app closure. - Async sync — high-level metrics (Club Reputation, Total Career Earnings) are queued and pushed to the Symfony API via TanStack Query offline mutations.
- Node.js 20.19.6 (
.nvmrcincluded — runnvm use) - Expo Go app on your device (iOS / Android)
nvm use
npm install --legacy-peer-deps# Start Metro + show QR code for Expo Go
npx expo start
# Run directly on simulator
npx expo start --ios
npx expo start --androidScan the QR code in Expo Go to load the app on your device.
The backend runs via Lando and is only accessible on 127.0.0.1. Use the dev proxy to expose it on your LAN so a physical device can reach it:
# Terminal 1 — start the dev proxy (bridges LAN → Lando)
npm run proxy
# Terminal 2 — start Metro
npx expo startSet the API base URL in .env:
EXPO_PUBLIC_API_BASE_URL=http://<your-machine-ip>:8080app/
├── _layout.tsx # Root layout (QueryClient, font loading, auth gate)
├── (tabs)/
│ ├── _layout.tsx # Tab navigator (4 primary + hidden routes)
│ ├── index.tsx # Club Hub (SQUAD / COACHES / SCOUTS top tabs)
│ ├── advance.tsx # Advance Week screen
│ ├── coaches.tsx # Coaching staff
│ ├── facilities.tsx # Facility upgrades
│ ├── finances.tsx # Finance Hub (BALANCE / INVESTORS / SPONSORS / LOANS)
│ ├── inbox.tsx # Guardian Inbox
│ └── squad.tsx # Player roster
└── player/[id].tsx # Player detail (bio, radar, trait bars)
src/
├── api/
│ ├── endpoints/ # auth, marketData
│ ├── mutations/ # syncMutations
│ ├── client.ts # Fetch wrapper (401 → re-login → retry)
│ └── syncQueue.ts # Offline mutation queue
├── components/
│ ├── radar/ # PersonalityRadar (SVG octagon)
│ ├── ui/ # PixelText, PixelTopTabBar, Avatar, etc.
│ ├── AdvanceModal.tsx
│ ├── GlobalHeader.tsx # Persistent top bar (name | week/date | sync + inbox)
│ ├── OnboardingScreen.tsx
│ └── SyncStatusIndicator.tsx
├── constants/
│ └── theme.ts # WK color tokens, traitColor(), pixelShadow
├── engine/
│ ├── GameLoop.ts # Weekly Tick processor
│ ├── finance.ts # calculateWeeklyFinances(), calculateNetSalePrice()
│ ├── personality.ts # generatePlayer() — 8-trait Personality Matrix
│ ├── recruitment.ts # generateCoachProspect(), generateScout()
│ └── appearance.ts # Player appearance generation
├── hooks/
│ ├── useAuthFlow.ts # Bootstrap: players + coaches + scouts + market data
│ └── useSyncStatus.ts
├── stores/
│ ├── clubStore.ts # Reputation, balance, tier, sponsorIds, investorId
│ ├── authStore.ts # Token, email, userId
│ ├── coachStore.ts # Coaches (add/remove)
│ ├── facilityStore.ts # Facility levels (0–10)
│ ├── inboxStore.ts # Guardian messages + behavioral incidents
│ ├── loanStore.ts # Loans, repayments, limits
│ ├── marketStore.ts # Readonly API snapshot (agents/scouts/investors/sponsors)
│ ├── scoutStore.ts # Scouts (add/remove)
│ └── squadStore.ts # Players, setPlayers(), generateStarterSquad()
├── types/ # TypeScript types (Player, Coach, Club, Facility…)
└── utils/
├── gameDate.ts
├── storage.ts # Zustand StateStorage adapter for AsyncStorage
└── uuidv7.ts # Timestamp-ordered UUID generator
assets/
├── fonts/
├── images/
└── svg/ # Custom pixel art SVG icons
- Wunderkind Backend: Symfony 6.4 API (separate repo) — JWT auth, leaderboard sync, club management endpoints