SMART trip is a community-built schedule app for Sonoma-Marin Area Rail Transit (SMART). It runs on the web and ships as Capacitor-based iOS and Android apps.
This project is not affiliated with Sonoma-Marin Area Rail Transit.
- Static SMART train schedules with weekday and weekend service views
- Live trip updates from SMART GTFS-Realtime data, including delays, cancellations, and skipped stops when available
- Live SMART service alerts with unread state stored locally on-device
- Ferry connections for Larkspur trips
- Closest-station selection using device location
- Trip detail sheets with GPS-assisted distance-to-stop messaging and better in-motion progress inference
- English and Spanish UI
- Light, dark, and system theme support
- Fare lookup for supported rider categories
- Shared web, iOS, and Android codebase
- React 18 + TypeScript
- Vite
- Tailwind CSS + Radix UI primitives
- TanStack Query
- React Router
- Capacitor for iOS and Android
- Vercel serverless functions for GTFS-Realtime proxying
- Node.js 18+
- npm
- A 511.org API key for live GTFS data
git clone <repository-url>
cd smart-trip
npm installCreate .env.local with:
TRANSIT_511_API_KEY=your_key_hereFor the full app, including local serverless API routes:
npm run dev-vercelFor frontend-only development:
npm run devIf you use npm run dev, real-time endpoints only work when either:
USE_SAMPLE_DATA=trueis set in.env.local, or- a local API target is running at
http://localhost:3000, or DEV_API_PROXY_TARGETin.env.localpoints/apiat another backend such as a feature-branch deployment
Default local URL:
http://localhost:3210
| Variable | Where | Purpose |
|---|---|---|
TRANSIT_511_API_KEY |
.env.local or Vercel env |
511.org API key for static and realtime feeds |
USE_SAMPLE_DATA |
.env.local |
Serve fixtures from sample/ instead of the live API |
DEV_API_PROXY_TARGET |
.env.local |
Dev-only /api proxy target for npm run dev; defaults to http://localhost:3000 |
VITE_API_BASE_URL |
.env.native or .env.native.local |
Absolute API base URL for native builds |
For production on Vercel, keep TRANSIT_511_API_KEY server-side only.
npm run dev- Start the Vite dev servernpm run dev-vercel- Start Vercel dev on port 3210npm run build- Type-check and build the web appnpm run build-native- Type-check and build the native web bundlenpm run preview- Preview the production buildnpm run lint- Run ESLintnpm run typecheck- Run TypeScript in build mode without emitting filesnpm run test:unit- Run unit tests with Vitestnpm run update-transit- Refresh GTFS schedule source data from 511.orgnpm run update-build- Refresh transit data, then buildnpm run sync- Build native bundle and sync Capacitor projectsnpm run sync-live- Sync Capacitor projects for live reload developmentnpm run assets- Generate app icons and splash screensnpm run open-ios- Open the iOS project in Xcodenpm run open-android- Open the Android project in Android Studio
Static schedule data is generated into src/data/generated/ and published to public/data/schedules.json during prebuild.
Realtime data flows through Vercel serverless routes:
511.org GTFS-Realtime
-> /api/gtfsrt/alerts
-> /api/gtfsrt/tripupdates
-> React Query hooks
-> trip cards, trip detail sheets, and service alerts UI
Trip updates are matched against static schedule entries by scheduled origin departure time because SMART trip IDs are regenerated per service date.
Native builds use Capacitor and read VITE_API_BASE_URL from .env.native so app requests go to a deployed API base instead of relative web paths.
Use .env.native.local for developer- or branch-specific overrides such as a PR deployment URL. That file is already ignored by Git.
Typical flow:
npm run sync
npm run open-ios
# or
npm run open-androidFor live reload on device or simulator:
npm run dev-vercel
npm run sync-livesync-live uses your Mac's Wi-Fi IP address. The device and development machine need to be on the same network.
- The app can request location permission for closest-station selection and GPS-assisted trip detail messaging.
- Location stays on-device and is not sent as part of schedule or realtime API requests.
- The app stores a small amount of local state such as theme, language, fare preference, and dismissed/read alert state.
- The web app includes Vercel Analytics; native builds do not mount that analytics client.
api/ Vercel serverless realtime proxy routes
public/ Static assets and hosted support/privacy pages
sample/ Local GTFS-Realtime fixtures
scripts/ Feed update and build helper scripts
src/components/ UI components
src/data/ Static and generated schedule data
src/hooks/ App hooks
src/lib/ Utilities and app logic
src/pages/ Route-level pages
src/types/ Shared TypeScript types
ios/ Capacitor iOS project
android/ Capacitor Android project
npm run test:unitnpm run build
npm run lint currently fails in this repo because of pre-existing issues in generated Android build output and unrelated source files.
The code in this repository is available under the MIT License. See LICENSE.
The SMART trip name, logo, and other project branding are not granted under the code license.
Built with ❤️ for the SMART Train community