3
Apps
30 Hz
IMU Capture
6-axis
Sensor Channels
Offline-first
Architecture
Starpilot is a data-collection platform where contributors use a mobile app to record video sessions with simultaneous IMU (Inertial Measurement Unit) sensor data capture — accelerometer and gyroscope at 30Hz. An admin web panel lets reviewers approve sessions and manage contributor payments, while a separate multi-language signup site handles contributor onboarding.
The mobile app is built with an offline-first architecture: sessions can be recorded without network connectivity, stored locally with automatic synchronization when connectivity returns. An upload manager with retry logic and S3 presigned direct uploads ensures reliable data transfer even on unreliable networks.
The admin panel serves as the central operations hub, providing a review queue for recorded sessions, video playback with cut timestamp editing, quality assessment, and automatic payment generation upon session approval.
The offline-first architecture uses a layered approach: offline sessions get temporary IDs (offline_*), stored in an AsyncStorage-backed offline session store. When connectivity returns, the sync process creates the server-side session, then physically renames the local recording directory from the offline ID to the server ID — avoiding expensive re-copying of large video files.
The upload queue is persisted in AsyncStorage and processed serially (FIFO) with a maximum of 3 attempts per item. Each upload is idempotent: the server checks if the S3 object already exists before issuing presigned URLs, and the client skips upload if alreadyUploaded is true. Background task processing via expo-background-task ensures uploads continue when the app is backgrounded.
IMU recording runs at ~30Hz (33ms interval) using expo-sensors DeviceMotion as the primary source, providing full acceleration, rotation rate, and gravity-separated acceleration. If DeviceMotion is unavailable, it falls back to separate Accelerometer + Gyroscope subscriptions. Data is buffered in memory and flushed every ~150 lines to a JSONL file, with a header recording wall clock start time, sensor timestamp start, and interval.
The dual Clerk setup solves a real problem: mobile app users and admin users need completely separate identity pools. The middleware inspects the request path — /api/app/* routes use the mobile Clerk instance (matching the Expo app's ClerkProvider), while all other routes use the admin Clerk instance. This avoids deploying two separate backends.
Video compression is handled by an Azure microservice triggered asynchronously: when a session moves to IN_REVIEW, the API presigns both a download URL for the original and an upload URL for the compressed preview, then POSTs to the compression server. The server transcodes and PUTs the preview directly to S3, then calls back via webhook to mark the session as compressed.
Crash recovery is built-in: active recording sessions are tracked in persistent storage. On the next app launch, bulkMarkRecorded reconciles any sessions stuck in RECORDING state — handling cases where the app was killed mid-recording.