Two purpose-built applications share a single real-time backend — a web dispatch console for coordinators and a mobile driver app for drivers in the field — connected through Convex's reactive database with Clerk-powered identity for drivers.
Web-first dashboard for coordinators to schedule routes, assign drivers to children, manage SMS communications, and monitor daily operations.
- stackExpo Router (web) · React Native · TypeScript
- deployNetlify —
git push master→ auto-deploy - authCustom bcrypt — shared login via
authUserstable - screensDispatch grid · CRM · SMS Switchboard · Payroll · Schools · Intake Review
- realtimeLive route status, driver updates, SMS inbox — all via Convex reactive queries
- publishPublic manifest URLs (
/public/:slug) for sanitized daily dispatch view - noteClerk auth is scaffolded (comments in
_layout.tsx) — ready for future upgrade
Native iOS/Android app for drivers to view their daily routes, log pickup status, message dispatch, and navigate to stops — fully authenticated via Clerk.
- stackExpo Router · React Native · TypeScript · EAS Build
- deployEAS Build → TestFlight (iOS) + Google Play (Android)
- auth🔐 Clerk —
ClerkProvider + ConvexProviderWithClerk· JWT inSecureStore - identityClerk
userId→drivers.clerkId— driver record linked at first sign-in viaby_clerk_idindex - tabsRoutes · Messages · Directory · Profile
- pushExpo Push Token stored in
drivers.expoPushToken— dispatch can push to any driver - i18ni18next — English, Portuguese (pt-BR), Spanish. Matches driver primary language field.
- drivers clerkId indexed
- children
- parents
- schools · districts · clients
- vehicles
- routes by_date_period
- stops
- dispatchEvents
- scheduleTemplates
- dailySummaries
- public_manifests
- smsMessages
- smsTemplates
- smsRecipients
- smsCampaigns
- groupConversations
- groupMessages
- optouts
- notifications
- auditLogs
- payrollConfig · baseRates
- transportationRequests
- sheetNameMappings
- crmContacts
- contactNames
queries
mutations
actions
http.ts (Twilio webhooks)
crons.ts
auth.config.ts (Clerk domain)
ConvexProviderWithClerk bridges JWT to Convex. Driver's clerkId stored in drivers table. Tokens cached in expo-secure-store for offline resilience.importFromSheet.ts syncs to Convex with fuzzy name matching via sheetNameMappings table — resolves informal aliases like "Abdul" to canonical records.drivers.expoPushToken. Dispatch triggers from coordinator actions.git push master triggers automatic deployment. Zero-config from Expo Router's web output. Production URL for coordinator access from any browser.Driver sign-in: Clerk authenticates driver → JWT passed to ConvexProviderWithClerk → Convex validates token → driver record fetched by drivers.by_clerk_id index → driver sees their routes.
Daily dispatch: Coordinator opens dispatch console → queries routes by_date_period → assigns driver to child → dispatchEvent created → SMS notification triggered to parent via Twilio.
Pickup confirmation: Driver taps "Picked Up" in mobile app → Convex mutation updates routes.pickedUpAt + routes.childPresent → dispatchEvent emitted → parent receives SMS confirmation in real-time.
Roster import: Admin exports Google Sheet → importFromSheet action runs fuzzy name matching against sheetNameMappings → confirmed matches upsert driver/child records → available in both apps instantly.
Inbound SMS reply: Parent replies "Running late" → Twilio webhook hits Convex /twilio/inbound → message stored in smsMessages with direction: "inbound" → appears in dispatcher's SMS inbox in real-time.
Public manifest: Coordinator clicks "Publish" → public_manifests record created with sanitized names and a unique slug → shareable URL requires no login → school staff or parents can verify pickup roster.