Skip to content
GuidesBlogPlaygroundDashboard

Build a Commute Time Comparison Tool

A Python script that compares commute times from multiple neighborhoods to your workplace, with a bonus isochrone showing everywhere you could live within 30 minutes.

New job, need to figure out where to live. This app takes your work address and a list of neighborhoods, calculates driving and cycling commute times for all of them in one shot, and draws a 30-minute isochrone so you can see everywhere that’s within range.

  • Geocoding to resolve addresses to coordinates
  • Distance matrix to get all commute times in a single request (instead of N individual routes)
  • Isochrone to draw a “30 minutes by car” polygon around the workplace

The core trick is the distance matrix — one API call gives you commute times from every neighborhood to the office, for both driving and cycling.

Batch commute calculation. Instead of routing each neighborhood individually, send all origins against a single destination. Two calls (driving + cycling) cover everything.

origins = [{"type": "Point", "coordinates": [h["lng"], h["lat"]]} for h in neighborhoods]
destinations = [{"type": "Point", "coordinates": [workplace["lng"], workplace["lat"]]}]
drive_matrix = await plaza_client.distance_matrix(
client, origins, destinations, profile="car"
)
cycle_matrix = await plaza_client.distance_matrix(
client, origins, destinations, profile="bicycle"
)

Each matrix response has durations and distances as 2D arrays. durations[i][0] is the time in seconds from neighborhood i to the workplace.

Generate a 30-minute driving isochrone. One call draws the polygon of everywhere reachable within 30 minutes from work.

iso = await plaza_client.isochrone(
client,
center={"type": "Point", "coordinates": [workplace["lng"], workplace["lat"]]},
contours_minutes=30, profile="car",
)

Check which neighborhoods fall inside. The app uses a simple ray-casting point-in-polygon test against the isochrone geometry to tag each neighborhood as within or outside the 30-minute zone.

def _point_in_polygon(lat, lng, geojson):
for feat in geojson.get("features", []):
geom = feat.get("geometry", {})
if geom["type"] == "Polygon":
rings = geom["coordinates"]
elif geom["type"] == "MultiPolygon":
rings = [r for poly in geom["coordinates"] for r in poly]
for ring in rings:
if _ray_cast(lng, lat, ring):
return True
return False

The distance matrix endpoint solves an N-to-M routing problem in one request. You send N origins and M destinations; it returns an N x M grid of travel times and distances. For this use case, M is always 1 (your office), so you get back a column of commute times.

The isochrone is a polygon that represents everywhere reachable within a given time. It complements the matrix nicely — the matrix gives you exact numbers for specific neighborhoods, while the isochrone shows you the full picture of what’s in range, including areas you hadn’t thought of.

The complete app (FastAPI backend + Vue frontend with map) is at github.com/plazafyi/example-apps/tree/main/real-estate-commute.

Stack: Python, FastAPI, Vue, Plaza API. The frontend renders neighborhoods as markers (green inside the isochrone, red outside) and displays the comparison table.

Rush hour commutes. Add depart_at to factor in traffic patterns. Morning: "depart_at": "2025-03-20T08:30:00". Evening: "depart_at": "2025-03-20T17:30:00".

Multiple time contours. The isochrone endpoint accepts comma-separated times: contours_minutes=10,20,30 gives you three nested polygons in one call. Good for showing how the reachable area expands.

Transit proxy. Switch the matrix mode to foot for walking time. Actual public transit routing isn’t available yet, but walking time to the nearest transit stop is a decent proxy for transit accessibility.

Weighted scoring. Commute time isn’t everything. Pull in neighborhood amenities (grocery stores, parks, restaurants) using PlazaQL, then build a weighted score: 0.4 * commute + 0.3 * walkability + 0.3 * amenities.

Interactive version. The example app already does this with Vue + MapLibre. You could also build it with plain HTML and Leaflet if you want something lighter.