PTdog
PTdog is a public transit accessibility watch for Klang Valley. It helps riders, carers, volunteers, and station teams see when a station is difficult to use, compare a faster route with a safer one, and share updates from the ground.
About the Project
Inspiration
Trip planners are good at showing where trains go, but they usually do not show whether a station is actually usable right now. A broken lift, a blocked ramp, or a crowded interchange can turn a technically valid route into a failed trip.
PTdog was inspired by that gap. We wanted to build something small but practical:
- a live ledger of station accessibility conditions
- a map that makes trouble spots easy to scan
- a route planner that values usability, not just speed
- a simple reporting loop so the next rider has better information
What the app does
PTdog focuses on three core jobs:
- Show current station conditions for lifts, escalators, ramps, and crowding
- Compare the fastest route with a safer, step-free-biased route
- Let people add fresh reports when conditions change
The result is a tool that answers a more useful question than "is there a route?"
It answers: "can I actually complete this trip?"
How we built it
The app is built as a small full-stack TypeScript project:
React 19+Vitefor the interfaceExpressfor the backend APILeafletfor the station map- shared TypeScript types in
shared/ledger.ts - persistent report storage through a local JSON file, with optional Google Cloud Storage fallback
The frontend presents:
- station cards with status summaries
- an inspection panel with recent reports
- a reporting form for new accessibility notes
- a planner that compares route choices
The backend handles:
- station seed data
- report validation
- merged station status
- dispatch notes and metrics
- persistence for user-submitted reports
We also added GTFS utilities so the project can grow beyond a static demo and connect to richer transit data over time.
Route logic
The route planner is intentionally simple. Each path cost is treated as travel time plus accessibility risk:
$$ \text{cost(path)} = \sum_{e \in path} t_e + \sum_{s \in path} p(s) $$
Where:
- (t_e) is travel time across each connection
- (p(s)) is a penalty based on station condition
- critical stations can be avoided entirely in step-free mode
That lets PTdog distinguish between the fastest path and the most usable path.
Challenges we faced
- Translating messy real-world accessibility problems into a clean data model
- Designing a status system that is simple enough to read quickly but still useful
- Making route logic feel practical without pretending to be a full transit engine
- Keeping the reporting flow lightweight so users can contribute without friction
- Balancing a polished interface with honest constraints in the current demo scope
What we learned
- Accessibility data is only useful if it is timely and easy to trust
- A small amount of structured ground-truth reporting can be more valuable than a polished but static map
- "Fastest route" is often the wrong default when physical access is the real constraint
- Good product framing matters: this is not just a map, and not just an incident board, but a decision tool
Project Structure
src/ Frontend app
server/ Express backend, ledger logic, GTFS helpers
shared/ Shared TypeScript types
data/ Local persisted report store
dist/ Production build output
Run Locally
Prerequisites: Node.js
- Install dependencies:
bash npm install - Start the app:
bash npm run dev - Open the client in your browser. Vite will usually serve it on
http://localhost:3000or the next free port.
Optional Environment Variables
PTdog runs without extra configuration for local use, but these variables are supported:
PORT=4000
PTDOG_LEDGER_FILE=data/ledger-store.json
PTDOG_GCS_BUCKET=your-bucket-name
PTDOG_GCS_OBJECT=ptdog/ledger-store.json
Why this project matters
Accessible transit is not only about whether infrastructure exists. It is about whether that infrastructure is working when people need it.
PTdog is a small attempt to make that visible.
Built With
- cloudrun
- express.js
- gcs
- gemini
- react
Log in or sign up for Devpost to join the conversation.