Skip to content

Technical description

How Commute is built

Every number on the site comes from a public source and a deterministic rule. This page says which, and what talks to what.

Shape of the system

The browser runs a Next.js app with a MapLibre map and talks only to the backend over JSON with a bearer token. The backend is a FastAPI service on Render with a managed Postgres, and it alone talks to the data providers, so caching, time budgets and the honesty labels live in one place.

Five providers, none of them needing a key: postcodes.io for coordinates, OSRM for car, cycle and walking routes, the TfL Journey Planner for bus and tube journeys, Open-Meteo for the next three hours of weather, and the gov.uk conversion factors with HMRC fuel rates, read once and pinned in code.

Frontend

One MapLibre map is mounted for the whole page. With nothing chosen it is a globe over the UK that sways slowly; a postcode flies the camera from orbit to the street in 3D. Routes are line layers on top, one colour per mode, the selected route wider and shared-car routes dashed. The panel is one component in two layouts, a card on desktop and a bottom sheet on phones, and every string lives in a single copy file so a linter can enforce house style.

PieceWhat it is
FrameworkNext.js 15 App Router, React 19, TypeScript strict
StylingTailwind CSS with design tokens as CSS variables, light and dark from one class
Componentsshadcn/ui-style components on Radix primitives, lucide icons, framer-motion; every one listed with licence in UI-COMPONENTS.md
MapMapLibre GL JS 5 with the globe projection; tiles and 3D buildings from OpenFreeMap (OpenStreetMap data)
Teststsx unit tests, ESLint, strict typecheck, a copy linter, a Tailwind class-merge guard

Backend

Four tables: profiles (home, the cached car route to the office, the shared-ride settings), saved places, trips (CO2, saving, XP, whether the arrival check passed) and carpool matches. XP is never stored as a total; it is the sum of a user's trips, so it cannot drift.

Planning a journey geocodes both postcodes, calls OSRM driving, cycling and walking and the TfL planner concurrently with a six second budget each, prices every option from the pinned factors, adds carpool candidates for a signed-in user, and asks Open-Meteo for the next three hours. Every option carries a provenance: routed, estimated (the public OSRM server returns a driving time for bike and foot, so those times are recomputed at 15 and 5 km/h and labelled) or unavailable. A failing provider never fails the request.

PieceWhat it is
FrameworkFastAPI 0.115 on Uvicorn workers under Gunicorn; Pydantic v2 for every request and response
DatabaseSQLAlchemy 2, Alembic migrations applied at boot, Postgres in production
AuthJWT bearer tokens, bcrypt password hashes, email verification; slowapi rate limits on every endpoint
Testspytest, 87 commute tests, no network: providers faked at the client seam

Carbon and money

Every CO2 and cost figure comes from a pinned factor with its source row named beside it in the code. The factors were checked against the published 2025 workbook and the HMRC page on 3 October 2026. Annual figures assume 220 working days, 440 one-way trips.

QuantityValueSource
Car, average, unknown fuel0.16725 kg CO2e per kmUK Government GHG conversion factors 2025
Local bus0.10385 kg CO2e per passenger kmsame, business travel (land)
London Underground0.02780 kg CO2e per passenger kmsame
Walk, cycle0
Fuel cost17p per mile, 10.6p per kmHMRC advisory fuel rates, petrol 1401 to 2000cc
Bus fare1.75 GBP per hour of bus legsTfL Hopper fare
Tube fare2.80 GBP per rail legassumption, named in the response

XP, the arrival check and the leaderboard

XP for a trip is the share of your own solo drive you avoided, from 0 to 100, plus 10 for sharing a car when the pair saves something. Cycle and walk pay 100, bus and tube about 80, a shared car between 35 and 50. Because it is a share and not a weight, a long commute earns no more than a short one: the leaderboard compares choices, not distances.

The server recomputes the option at log time and ignores any number the client sends. The same trip twice within 30 minutes is refused, trips under 1 km are logged without points, and only four trips a day score. A trip is verified when the phone is within 500 m of the destination and the time since Start is at least 60% of the routed duration; it deters rather than proves, and a GPS trace classifier is the next step.

The leaderboard ranks everyone by total XP, all time or this week from Monday 00:00 London. Weekly prizes go to the top three; milestones at 500, 1,500, 3,000 and 6,000 XP are badges kept for good.

Shared rides

The person who sends the request is the driver. Candidates are the six nearest homes among people who opted in; for each, OSRM routes driver home, partner home, office, and the candidate is kept when the detour adds at most 12 minutes. The detour and overlap are measured once from the driver's seat and stored, so both people see the same numbers.

The saving is the pair's total, both solo drives minus the shared drive, split equally; each traveller's XP is their share against their own baseline. The sharing bonus is only paid when there is a saving. Once a pair is accepted and both consented, each sees the other's phone number, and nowhere else is a number shown.

The organisers' resources

ResourceUsed for
gov.uk conversion factorsevery CO2 figure
OSRMcar, cycle, walk and carpool detour routes
Open-Meteothe weather suggestion
Bus Open Data (DfT)not used: it needs a key and gives timetables, not journeys; TfL's planner gives London journeys with no key
Nomisnot used in the app

Known limits

  • The public OSRM server is shared and rate limited; routes are cached 30 minutes.
  • Carbon factors are UK averages, not the user's actual car.
  • The arrival check deters rather than proves.
  • Carpool XP is paid to each traveller on their own log; a paired payout is designed, not built.