A real-time location tracking and monitoring mobile app built with Expo and React Native. It connects to a WebSocket server to receive and display live location updates and logs from multiple devices.
- Real-time WebSocket Connection - Auto-connects with exponential backoff reconnection
- Home Dashboard - Connection status, device count, message stats, and last update time
- Timeline View - Chronological list of location updates with device and route filtering
- Map View - Interactive map with device trajectories, markers, and auto-follow mode (native only)
- Log Viewer - Real-time log display filterable by type, level, and device with text search
- Dark Mode - Full light/dark theme support
| Layer | Technologies |
|---|---|
| Frontend | React Native, Expo (~54), React 19, TypeScript |
| Styling | NativeWind (Tailwind CSS), React Native Reanimated |
| Navigation | Expo Router (file-based routing) |
| Server State | TanStack React Query, tRPC |
| Backend | Express, tRPC, Drizzle ORM, MySQL |
| Auth | OAuth, JWT (jose), expo-secure-store |
- Node.js 18+
- pnpm 10.28.1
- Xcode (for iOS) or Android Studio (for Android)
- MySQL database server
# Install dependencies
pnpm install
# Set up environment variables
cp .env.example .env
# Edit .env with your values
# Run database migrations
pnpm db:push
# Start development (server + metro bundler)
pnpm dev| Command | Description |
|---|---|
pnpm dev |
Start server and Metro bundler concurrently |
pnpm dev:server |
Start the backend server with hot reload |
pnpm dev:metro |
Start the Expo Metro bundler |
pnpm ios |
Run on iOS simulator |
pnpm android |
Run on Android emulator |
pnpm build |
Bundle server for production (esbuild) |
pnpm start |
Run production server |
pnpm check |
TypeScript type checking |
pnpm lint |
Run ESLint |
pnpm format |
Format code with Prettier |
pnpm test |
Run tests (Vitest) |
pnpm db:push |
Generate and apply database migrations |
βββ app/ # Screens (Expo Router file-based routing)
β βββ (tabs)/ # Tab navigation (Home, Timeline, Map, Logs)
β βββ dev/ # Development routes
β βββ oauth/ # OAuth callback handling
βββ components/ # Reusable UI components
βββ hooks/ # Custom React hooks
βββ lib/ # Core libraries and state management
β βββ location-store.tsx # Location state (Context + useReducer)
β βββ trpc.ts # tRPC client configuration
β βββ types/ # TypeScript type definitions
βββ server/ # Backend (Express + tRPC)
β βββ routers.ts # API route definitions
β βββ db.ts # Database query helpers
β βββ _core/ # Framework internals
βββ shared/ # Code shared between client and server
βββ drizzle/ # Database schema and migrations
βββ constants/ # App-wide constants
βββ tests/ # Test files
| Variable | Description |
|---|---|
DATABASE_URL |
MySQL connection string |
JWT_SECRET |
Secret for JWT signing |
THQ_WS_AUTH_TOKEN |
WebSocket authentication token |
TRAINLCD_GQL_URL |
TrainLCD GraphQL API endpoint |
EXPO_PUBLIC_API_BASE_URL |
Backend API base URL (client-side) |
EXPO_PUBLIC_OAUTH_* |
OAuth configuration (client-side) |
Variables prefixed with
EXPO_PUBLIC_are exposed in the client bundle. Never put secrets there.