Linha Viva Porto is a web app that visualizes the live positions of STCP buses in Porto on an interactive map.
It provides a smooth, GPU-accelerated, real-time view of buses in motion with route details, stop information, and bus tracking capabilities.
- Live bus positions - Real-time visualization of all STCP buses on an interactive map
- Smooth animations - GPU-accelerated animations for hundreds of buses using WebGL
- Multiple map styles - Switch between different map styles (Voyager, Positron, Dark Matter)
- Interactive bus selection - Click any bus to view detailed information
- Visual focus - Selected buses remain at full opacity while others fade out
- Route visualization - View route paths and stops when selecting a route or bus
- Route dashboard - Browse all available routes with filtering and search
- Route filtering - Filter buses by specific route lines
- Route details - View complete route information including:
- Route path visualization
- All stops along the route
- Active buses on the route
- Direction switching (Outbound/Inbound)
- Stop timeline with progression tracking
- Bus selection - Select individual buses to track their position
- Active buses list - See all active buses for a selected route and direction
- Direction detection - Automatically detect bus direction based on position
- Route progression - Track which stops a bus has passed and which are next
- Search functionality - Search routes by name or number
- Network statistics - View total routes and active buses count
- Collapsible dashboard - Expandable sidebar for route management
- Responsive design - Optimized for various screen sizes
Preprocessed GTFS data stored in the repository:
- Routes and route metadata
- Stops and stop locations
- Trips and trip schedules
- Route shapes and paths
- Calendar and service dates
Location: public/data/stcp/
Urban Platform โ Bus Location (STCP)
OpenData Porto
- Real-time bus positions (latitude, longitude, bearing)
- Bus line information
- Periodic updates (~10โ15s intervals)
- Bun - Fast JavaScript runtime, package manager, and bundler
- Vite - Build tool and dev server (bundled with Bun)
- React 18 - UI library
- TypeScript - Type-safe development
- TailwindCSS - Utility-first CSS framework
- MapLibre GL JS - Open-source map rendering library
- WebGL - GPU-accelerated rendering
- GeoJSON - Geographic data format
- React Context API - Global state management
- Custom hooks for data fetching and map interactions
- GTFS parsing - Client-side GTFS data processing
- CSV Workers - Web Workers for parsing large GTFS files
- Geospatial calculations - Distance and direction calculations
Browser (Client-Side)
โโโ Static GTFS Data (public/data/stcp/)
โ โโโ routes.txt
โ โโโ stops.txt
โ โโโ trips.txt
โ โโโ shapes.txt
โ โโโ ...
โโโ Periodic API Fetch โ STCP Live Bus Positions
โโโ React Components
โ โโโ MapContainer (MapLibre GL)
โ โโโ RouteDashboard (Route list & filtering)
โ โโโ RouteDetail (Route information & stops)
โ โโโ NetworkStats (Live statistics)
โโโ Context Providers
โ โโโ AppContext (Global state)
โ โโโ RouteDetailContext (Route-specific state)
โโโ Custom Hooks
โ โโโ useBusPositions (Live bus data)
โ โโโ useBusLayer (Map bus rendering)
โ โโโ useRouteLayer (Route path rendering)
โ โโโ useRouteDetailData (Route information)
โโโ Services
โโโ busService (API integration)
โโโ gtfsService (GTFS data parsing)
All logic runs client-side - No backend, no database, no authentication.
- Bun (latest version)
-
Clone the repository
git clone <repository-url> cd linha-viva
-
Install dependencies
bun install
-
Run development server
bun dev
-
Open in browser Navigate to the URL shown in your terminal (typically
http://localhost:5173)
bun run buildThe production build will be in the dist/ directory.
Bus movement is animated smoothly using:
- Periodic API fetching - Fetch live positions at fixed intervals (~10-15s)
- Position interpolation - Store previous and next coordinates per vehicle
- RequestAnimationFrame - Interpolate positions between API updates
- GeoJSON updates - Update map source on each animation frame
- GPU acceleration - WebGL rendering handles hundreds of moving vehicles efficiently
This approach:
- โ Avoids marker "teleporting"
- โ Provides smooth, continuous movement
- โ Scales well to hundreds of buses
- โ Maintains 60fps performance
src/
โโโ components/
โ โโโ dashboard/ # Dashboard UI components
โ โ โโโ RouteDashboard.tsx
โ โ โโโ RouteDetail/ # Route detail components
โ โ โโโ FloatingSearch.tsx
โ โ โโโ NetworkStats.tsx
โ โโโ map/ # Map-related components
โ โโโ MapContainer.tsx
โ โโโ MapZoomControls.tsx
โโโ context/ # React Context providers
โ โโโ AppContext.tsx
โ โโโ RouteDetailContext.tsx
โโโ hooks/ # Custom React hooks
โ โโโ dashboard/ # Dashboard-related hooks
โ โโโ map/ # Map-related hooks
โ โโโ useBusPositions.ts
โโโ services/ # Data services
โ โโโ busService.ts # STCP API integration
โ โโโ gtfsService.ts # GTFS data parsing
โ โโโ csvWorker.ts # CSV parsing worker
โโโ types/ # TypeScript type definitions
โโโ constants/ # App constants
โโโ lib/ # Utility functions
- API dependency - App depends on the public STCP API; avoid aggressive polling
- Data quality - GPS accuracy and update frequency depend on STCP's data quality
- Browser compatibility - Requires modern browser with WebGL support
- GTFS data - Static GTFS files are included in the repo for offline reference
- No delay calculations - Real-time delay/lateness calculations are not currently implemented
Potential features for future development:
- Real-time delay and lateness calculations
- Backend caching layer for improved performance
- Historical data analysis
- User preferences and saved routes
- Mobile app version
- Offline mode with cached data
This project is open-source and uses public open data.
Check the original datasets for their respective licenses.
- STCP โ Sociedade de Transportes Colectivos do Porto
- Porto Digital โ Open Data Portal
- MapLibre โ Open-source mapping library
- OpenStreetMap โ Map data provider