Own product · in production
Trajecto+
Porto Metro timetables on your phone, in 7 languages and even with no signal inside the tunnel. An independent app that I designed and maintain end to end: from the interface to payments, from timetable import to the server.
trajectoplus.pt
The problem
Metro timetables are needed exactly where the signal drops: inside the tunnel. And Porto has many tourists, who need them in their own language.
What I built
An installable app with the next departures from each station, the lines, a journey planner with transfers and a tourist guide with 31 places of interest near the metro, with a map and photos. It is available in 7 languages: Portuguese, English, Spanish, French, German, Italian and Japanese.
Decisions
- Timetables on the phone. The timetables published by Metro do Porto (GTFS) are validated before each import and stored on the phone, so the app works offline. Even trains after midnight, which GTFS lists as 24:xx, belong to the previous day and show the right time.
- Maps without third parties. The Porto map is a tile set served from my own server, with no requests to external map services, and the user’s location never leaves the phone.
- Payment inside the app. In an app installed on an iPhone, opening the browser to pay lost the purchase, so the Stripe checkout opens inside the app. The pass is granted by the Stripe webhook, never by the browser coming back.
- Passes that stack. Buying a pass before the previous one ends doesn’t lose any days: the new one starts when the other finishes.
Operations
Everything runs in Docker, with Caddy handling HTTPS. Images are built on GitHub Actions, no deploy goes ahead unless the tests pass and, if the new version doesn’t respond, the server rolls back on its own. The database is copied every day at 03:00 and sent to a NAS at home, protected by snapshots.
Technology
React, TypeScript, Mantine and Leaflet on the frontend, FastAPI on the backend, MongoDB, Stripe, Docker, Caddy and GitHub Actions.
Technologies
- React
- TypeScript
- FastAPI
- MongoDB
- Stripe
- PWA