Skip to content

kevinngw/link

Repository files navigation

Link Pulse

Realtime transit board for Puget Sound, available as both an installable web app and a Capacitor-based iOS app.

Live Site | 中文说明

Overview

Link Pulse tracks live vehicles, arrivals, and service health across:

  • Link light rail
  • RapidRide bus rapid transit
  • Swift bus rapid transit

The project keeps one shared JavaScript UI and ships it in two forms:

  • a PWA web build for GitHub Pages
  • an iOS shell built with Capacitor

Highlights

  • Multi-system board with Map, Trains/Buses, Favorites, and Insights
  • Live arrivals and vehicle positions via Puget Sound OneBusAway
  • Station dialog with arrivals, alerts, favorites, sharing, and board display mode
  • Train detail dialog with previous/current/next stop and ETA-to-terminal
  • Station search across names, lines, systems, and nearby stations
  • Persistent preferences for theme, language, favorites, and recent searches
  • Bilingual UI in English and Simplified Chinese
  • iPhone polish for dialogs, board mode, map labels, icons, and splash screens

Stack

  • Vite + vite-plugin-pwa
  • Vanilla JavaScript (ES modules) + SVG rendering
  • Capacitor for iOS packaging
  • Capacitor plugins:
    • Preferences
    • Geolocation
    • Share
    • Clipboard
    • Haptics
    • Splash Screen
  • Vitest for unit tests

Requirements

  • Node.js 20.19+ or 22.12+
  • npm 10+
  • Xcode for simulator or device testing

Quick Start

npm install

# Optional: use your own OneBusAway key instead of TEST
cp .env.example .env.local
# Edit .env.local and set VITE_OBA_KEY=your_key

Static GTFS-derived data refresh is explicit:

npm run refresh:data

Use that when you want fresh source data. Routine web and iOS builds do not force a GTFS download first.

Common Commands

# Web dev
npm run dev
npm run dev:refresh

# Production builds
npm run build
npm run build:web
npm run build:native

# iOS sync / open
npm run cap:sync
npm run ios:open

# Local preview
npm run preview

# Tests
npm test
npm run test:run
npm run test:ui
npm run test:coverage

Web Development

npm run dev starts the Vite dev server. In this project, the web app is served under /link/, so the page is typically available at:

  • http://localhost:5173/link/

npm run build:web produces the PWA build:

  • service worker enabled
  • GitHub Pages base path /link/

iOS Development

The iOS app currently ships as:

  • App name: Link Pulse
  • Bundle ID: com.linkpulse.app
  • Scheme: LinkPulse

Relevant files:

Typical simulator/device loop:

# Build web assets for the native shell and sync them into ios/
npm run cap:sync

# Open the Xcode project
npm run ios:open

npm run build:native differs from the web build in two important ways:

  • it switches the base path to /
  • it disables PWA registration so the native shell does not ship a service worker

Native integrations live in src/native/:

Environment Variables

Variable Purpose
VITE_OBA_KEY OneBusAway API key. Falls back to public TEST if omitted.
VITE_TARGET Build target selector used by scripts (web or native).
VITE_BASE Override the base path for unusual deployments.
VITE_SHARE_BASE_URL Base URL used when generating shared station links.

The app works with the public TEST key, but refreshes more conservatively and backs off more aggressively after rate limiting.

Data Sources

Source Endpoint
Live vehicles Puget Sound OneBusAway vehicles-for-agency/{agencyId}.json
Stop arrivals arrivals-and-departures-for-stop/{stopId}.json
Static system data Generated by scripts/build-link-data.mjs from GTFS feeds and OBA geometry

Project Layout

docs/
  ios-app-store-readiness.md   iOS rollout and App Store notes
ios/
  App/
    App.xcodeproj/             Xcode project
    CapApp-SPM/                Capacitor Swift package bridge
    LinkPulse/                 App source, assets, plist, privacy manifest
public/
  icon.svg                     Web icon source
  splash-light.svg             Light splash source
  splash-dark.svg              Dark splash source
  pulse-data.json              Generated static transit data artifact
scripts/
  build-link-data.mjs          GTFS / OBA static data generator
src/
  dialogs/                     Station, train, alert, and overlay dialog logic
  native/                      Web/native adapters
  renderers/                   Map, train list, and insights renderers
  main.js                      App shell and UI wiring
  static-data.js               Static data loading and bootstrap
  station-search.js            Search and nearby lookup
  favorites.js                 Favorite station management
  recent-stations.js           Recent station session state
  style.css                    Global styles
capacitor.config.json          Capacitor app config
vite.config.js                 Web/native Vite build config

Deployment

Web deploys are published through deploy.yml.

Branch URL
main https://kevinngw.github.io/link/
dev https://kevinngw.github.io/link/dev/

App Store Notes

This repo already includes the basics needed for iOS packaging:

  • native app shell via Capacitor
  • iOS app icons and splash assets
  • PrivacyInfo.xcprivacy
  • location usage copy in Info.plist
  • native-safe storage, geolocation, sharing, haptics, and splash handling

Longer implementation and review notes live in docs/ios-app-store-readiness.md.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors