{
  "markdown": "# isochrone\n\n[![demo](https://img.shields.io/website?url=https%3A%2F%2Fiso.huseyincapan.dev%2Fhealthz&up_message=live&down_message=down&label=demo)](https://iso.huseyincapan.dev)\n[![uptime](https://github.com/capan/isochrone/actions/workflows/uptime.yml/badge.svg)](https://github.com/capan/isochrone/actions/workflows/uptime.yml)\n\n**Live: [iso.huseyincapan.dev](https://iso.huseyincapan.dev)**\n\nClick anywhere on the map and see the street network you can actually reach on\nfoot within 15 minutes — coloured by arrival time, with mobility profiles that\naccount for stairs and unpaved paths.\n\nOSM data → PostGIS + pgRouting → Express → Leaflet.\n\n<img src=\"docs/hull-vs-network.png\" width=\"660\" alt=\"Same corner, same 15 minutes, drawn two ways: the reachable street network against the hull drawn around it\">\n\n## Why not a polygon?\n\nEvery isochrone map I could find answers with a filled polygon. That is wrong\nunless you are a pigeon: a polygon claims you can reach the middle of a block,\ncross a rail cutting, walk through a building. On the corner above, the same\n15 minutes gives you 107.6 km of reachable streets; the hull drawn around them\ncovers 3.28 km² and claims 30.4 km of street the walk cannot actually reach.\nThis map draws the network.\n\n## How it works\n\n`pgr_drivingDistance` walks the street graph from the vertex nearest your click\nuntil the time budget runs out, and returns every reachable edge with its\narrival time. Those edges are grouped into 10 equal time bands and drawn\ndirectly.\n\nEdge cost is `length / speed` in seconds, computed per request from the\nselected profile, so a profile is a few numbers rather than a schema change:\n\n| profile | speed | stairs | unpaved |\n|---|---|---|---|\n| `walk` | 1.4 m/s | half speed | normal |\n| `stroller` | 1.2 m/s | impassable | 0.6× |\n| `wheelchair` | 0.9 m/s | impassable | impassable |\n\nThese factors are estimates, not measurements — see *Known gaps*.\n\n## Where should I live?\n\nAnswer a short questionnaire weighting seven everyday layers (dining, green\nspace, playgrounds, groceries, health, kindergartens, schools) and the whole\nBerlin map re-ranks to show where *your* weighted 15-minute city actually is,\nas walk, bike or wheelchair.\n\nThe trick is that nothing is routed at question time: 21 full-city\nreachability surfaces (7 layers × 3 profiles, ~134,000 grid cells each) are\nprecomputed offline, so re-ranking the city is one aggregate query. Stroller\nis deliberately absent here: its speed factors are uncalibrated estimates and\nmust not be published as if measured.\n\n## Ask Claude about it (MCP)\n\nThe [`isochrone-mcp`](https://www.npmjs.com/package/isochrone-mcp) package lets\nany MCP client answer reachability questions against this API:\n\n```bash\nclaude mcp add isochrone -- npx -y isochrone-mcp\n```\n\n<!-- 1320px source shown at 660 — 2x density, so it stays sharp on retina -->\n<img src=\"mcp/demo.gif\" width=\"660\" alt=\"Claude answering a reachability question, then the isochrone drawn on the map\">\n\nOne tool, `reachable_area`: origin + minutes + profile, optional target\n(\"can I get there in time?\"). Returns a prose summary and a map link, not\ncoordinate soup. Details in [mcp/](mcp/).\n\n## Known gaps\n\n- **Graph islands.** The vertex nearest a click can sit on a disconnected\n  fragment — `52.515,13.400` reaches 13 nodes. Fix is a one-time\n  `pgr_connectedComponents` table for the vertex lookup to join against.\n- **Calibration.** The speeds above are guesses. Google's Isochrones API\n  (Preview) supports `WALK` and returns GeoJSON, so the `walk` profile could be\n  calibrated against it. It has no stroller/wheelchair mode, so those stay\n  unvalidated.\n- **Stranded origins** render as a tiny blob rather than saying \"unreachable\n  with this profile\".\n\n## Running it yourself\n\nDev setup, deployment, city import and the ops notes live in\n[docs/OPERATIONS.md](docs/OPERATIONS.md).\n",
  "bytes": 3868,
  "sha": "0ea299322c66e84504163dff1a4886a4e0efa1c2d1af7a23b99c37658f316957",
  "repo_slug": "capan/isochrone",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_capan_isochrone_c0a4a75e/readme"
}