Skip to content

passengers-app — CONTEXT.md

Ionic 8 / Angular 20 passenger-facing mobile app. Route search, real-time bus tracking, QR check-in/out, and wallet payments. Deployed via Capacitor to iOS and Android. For global conventions (branding, Angular patterns, GIS overview), see /CLAUDE.md.


1. Tech Stack

Layer Technology Version
Framework Ionic + Angular Ionic ^8.0, Angular ^20.0.0
Maps Leaflet ^1.9.4
Native Capacitor ^8.2.0
GPS @capacitor/geolocation ^8.1.0
Storage @capacitor/preferences ^8.0.1
Notifications @capacitor/local-notifications ^8.0.2
QR Generate qrcode ^1.5.4
QR Scan html5-qrcode ^2.3.8
Real-time socket.io-client ^4.8.3
Styling Tailwind CSS ^3.4.19
Particles tsparticles ^3.9.1
Build @angular/build (esbuild) ^20.0.0

Capacitor Config

  • appId: com.syncc.passengers
  • appName: Syncc Pasajero
  • webDir: www
  • Android scheme: https
  • iOS: contentInset: automatic, limitsNavigationsToAppBoundDomains: true

2. Routes

Path Component Notes
/home HomePage Route search, suggestions, real-time map
/route-detail/:lineId/:routeId RouteDetailPage Route detail with map + checkpoints
/gtfs-route-detail GtfsRouteDetailPage GTFS route detail (state-passed data)
/nearby NearbyPage Nearby stops/lines
/lines LinesPage Browse all lines
/lines/:id LineDetailPage Single line detail
/favorites FavoritesPage Saved routes/lines
/login LoginPage OTP-based passenger auth
/profile ProfilePage Profile, balance, recharge
/my-qr MyQrPage Passenger QR display
/scanner ScannerPage QR scanner (check-in)
/ Redirects to /home
** Redirects to /home

All routes use lazy loading via loadComponent.


3. Core Services

All services in src/app/core/services/, providedIn: 'root'.

Service Purpose
AuthService Passenger login/signup; OTP flow; currentUser signal; JWT validation
TokenService JWT persistence via Capacitor Preferences (syncc_pax_token)
RealtimeService Socket.IO connection; buses signal (Map)
LinesService HTTP calls for lines, routes, checkpoints, stops
BoardingService QR check-in/out; active boarding session; state persistence
PaymentIntentService "Pagar con saldo" intent signals (enabled, amount)
PaymentService Recharge flow; payment gateway integration
FavoritesService Favorite routes/lines; persisted to Preferences
HistoryService Search history; persisted storage
SuggestionsService Route suggestions based on history/favorites
PermissionService Capacitor permissions (geolocation, camera, notifications)
DrawerService Navigation drawer state (isOpen, overlayOpen signals)
OsrmService Road-snapping via OSRM public server (foot profile, 6s timeout)

4. OSRM Walking Legs

Walking legs (origin → board stop, alight stop → destination) use the OSRM foot profile: - Called from the browser/device — never proxied through the backend - URL: https://router.project-osrm.org/route/v1/foot/{lng1},{lat1};{lng2},{lat2}?overview=full&geometries=polyline - Timeout: 6 seconds - Falls back to straight line if OSRM is unreachable - Used in home.page.tsdrawTripOnMap() and route-detail.page.tsinitMap()


5. Environment Config

set-env.cjs reads --environment=local|dev|prod and generates environment files: - Local: loads .env → writes environment.local.ts (localhost:3000) - Dev: loads .env.development → writes environment.ts (api.dev.syncc.me) - Prod: loads .env.production → writes environment.prod.ts - Searches for .env in: ./, ../api-server/, ../../ - Required env var: API_URL


6. QR / Payment Feature — Restore Instructions

Trigger: "implement the QR functionality" or "activate the QR functionality".

All QR/payment UI is hidden with @if (false) blocks (not deleted). To restore:

src/app/app.component.html — Three blocks:

  1. "En el bus" boarding banner (line ~155): @if (false)@if (activeBoarding()) Shows boarding status banner with line name and elapsed time.

  2. QR floating action button (line ~188): @if (false)@if (isLoggedIn() && !overlayOpen()) Circular FAB at bottom-center that opens QR modal.

  3. QR modal full screen (line ~201): @if (false)@if (qrModalOpen()) Contains scan tab (html5-qrcode scanner), show-QR tab, and "Pagar con saldo" toggle with amount input.

src/app/pages/profile/profile.page.html — Two blocks:

  1. Balance card (line ~25): HTML comment block <!-- NOT LAUNCHING YET: Balance card ... END NOT LAUNCHING YET --> — delete the comment wrapper lines. Shows "Saldo disponible" with Bs. amount and "Agregar saldo" button.

  2. Recharge modal (line ~107): @if (false)@if (rechargeStep() !== 'idle') Multi-step modal: amount → processing → success/error.

What does NOT need to change

  • All TypeScript services are intact (BoardingService, PaymentIntentService, PaymentService)
  • Routes /my-qr and /scanner exist and are routed — just not reachable from hidden UI
  • DrawerService.overlayOpen / showOverlay() / hideOverlay() already wired

After restoring

npm run cap:ios    # or npm run cap:android

No backend changes needed — all API endpoints are already live.


7. Dev Workflow

cd apps/passengers-app
npm install
npm start                  # Dev server at http://localhost:4200
npm run build:prod         # Production build
npx cap sync               # Sync Capacitor native projects
npx cap run android        # Run on Android
npx cap run ios            # Run on iOS

8. Key File Paths

What Path
Routes src/app/app.routes.ts
App component src/app/app.component.ts / .html
Services src/app/core/services/
Pages src/app/pages/
OSRM service src/app/core/services/osrm.service.ts
Profile page src/app/pages/profile/profile.page.ts / .html
Environment config set-env.cjs
Capacitor config capacitor.config.ts
Tailwind config tailwind.config.js

Last updated: 2026-06-05.