尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Accessible walking routes for the University of Waterloo campus and uptown Waterloo, kept up to date by the people using them.
Passable plans routes for three profiles:
Every route says how much it trusts the map data (mapped, assumed or not mapped). Anyone can report a hazard, such as an elevator that's out, a blocked sidewalk, construction or ice. Reports change everyone's routes within seconds. Only the people whose route is affected get a "reroute?" prompt. Reports are confirmed or resolved by votes and expire on their own.
Live: https://passable-alpha.vercel.app · status · about & limitations · API: https://passable-api.fly.dev
You need Docker, Go 1.27+, Node 20.9+, plus curl and jq.
git clone https://github.com/PrateekGithub23/passable && cd passable
docker compose up -d --wait # Postgres+PostGIS on :5433, Redis on :6379
go run ./cmd/migrate # create the schema
scripts/fetch_osm.sh # download campus paths from OpenStreetMap (~1 min)
go run ./cmd/importer # build the routing graph: 21,173 path segments
go run ./cmd/api # API on http://localhost:8080 (leave running)
In a second terminal:
cd web && npm install && npm run dev # http://localhost:3000
Then, on the map:
go run ./cmd/simulator files clearly labelled demo hazards and cleans up when you press Ctrl-C.If OpenStreetMap's Overpass API rate-limits the download, wait a minute, or run OVERPASS=https://overpass.kumi.systems/api/interpreter scripts/fetch_osm.sh.
flowchart LR
B["Browser<br/>Next.js + MapLibre"] -->|"REST: route, report, vote"| API
API -.->|"WebSocket: hazards, reroute prompts"| B
subgraph API["Go API"]
direction TB
R["A* router"] --> S["one snapshot per query<br/>(atomic.Pointer)"]
S --> G["immutable graph<br/>+ per-profile costs"]
S --> O["copy-on-write<br/>hazard overlay"]
end
API -->|"snapping, reports, event log"| PG[("PostgreSQL + PostGIS")]
API <-->|"route cache, pub/sub, rate limits"| RD[("Redis")]
length × multiplier + penalty, or blocked. Missing data is penalized and labelled, never silently assumed fine.More detail: architecture and request flows · every design decision and what was rejected · API reference.
All numbers come from real runs; details in docs/benchmarks/.
| What | Result | Source |
|---|---|---|
| One route search (A*, wheelchair, 2000 random campus queries) | p50 0.50 ms, p99 2.7 ms, ~2,100 nodes expanded | cmd/bench, Day 8 |
| HTTP load, 1,000 route requests/s with hazards changing every second | 0 failures in 30k requests, p95 5.6 ms, p99 12.3 ms | k6, day8.md |
| Route cache (stable graph version) | 40% hit rate; hit p95 1.0 ms against 5.0 ms for a miss | k6, day 8 |
| Report → WebSocket client, across two API instances | p50 6.3 ms, p95 8.4 ms, including the database write | cmd/wsprobe, day6 |
| Concurrency: routes vs. hazard writes | 27,055 routes during 141,586 snapshot swaps, all consistent, race detector clean | overlay stress test |
| Production: route not in the cache, server time | 11.6 ms average (mostly the two database queries between Fly and Neon) | /metrics on Fly |
| Production: report in one browser → prompt in another | 470 ms end to end, both over the internet | two-browser test on the live site |
OpenStreetMap data for the bbox 43.455,-80.565,43.485,-80.505, fetched 2026-10-24.
| Data | Coverage |
|---|---|
| Graph | 15,468 nodes, 21,173 edges, 703 km of paths and streets |
| Surface tagged (footways and paths) | 70% of edges; the rest are labelled inferred (sidewalks, roads) or unknown |
| Steps / crossings / kerbs | 237 steps edges, 2,167 crossing edges (1,177 with kerb data), 1,277 kerb nodes |
Smoothness / incline / wheelchair tags | 1.3% / 0.1% / 0.1% of footway, path and pedestrian edges |
What that means:
incline is almost never tagged, so a steep path can be suggested to a wheelchair user.Full numbers are in Data coverage details below.
go test -race ./... # unit, property and golden tests; no Docker needed
go test -tags integration -race ./integration # real PostGIS + Redis via testcontainers, 2 API instances
cd web && npm run lint && npm run typecheck # frontend
k6 run -e RATE=200 scripts/k6/load.js # load test (API started with -rate-limit=false)
testdata/).scripts/k8s-up.sh deploys the stack to a local kind cluster (2 API replicas, migration Job, probes, NetworkPolicies) and smoke-tests it, including a hazard crossing between replicas. See docs/KUBERNETES.md.main that passes deploys the API to Fly.io. The site deploys from the same push through Vercel (how deployment works).| Path | What's there |
|---|---|
cmd/api | The HTTP + WebSocket server |
cmd/importer, scripts/fetch_osm.sh, scripts/gate.sh | OpenStreetMap download, coverage check, graph import |
cmd/migrate, db/migrations | Schema migrations (goose, embedded in the binary) |
cmd/route, cmd/bench, cmd/wsprobe, cmd/simulator, cmd/exportgraph | CLI routing, benchmarks, propagation probe, demo simulator, test-fixture export |
internal/graph, internal/cost, internal/route | Graph, per-profile cost model, A* |
internal/hazard, internal/overlay, internal/reports | Hazard rules, copy-on-write overlay, persistence and lifecycle |
internal/live, internal/cache, internal/ratelimit, internal/metrics | WebSocket hub + Redis bus, route cache, rate limiting, Prometheus |
internal/api | Handlers, snapping, explanations, CORS, stats |
web/ | Next.js frontend (/, /about, /status) |
integration/, testdata/, scripts/k6/ | Integration tests, graph fixture, load test |
deploy/k8s/, scripts/k8s-up.sh | Kubernetes manifests (Kustomize) and the kind deploy + smoke test |
docs/ | Architecture, API, deployment, Kubernetes, benchmarks, demo script |
OSM tag counts (scripts/gate.sh; "ped ways" = highway footway/path/pedestrian)
| Metric | Count |
|---|---|
| Ped ways | 5,239 |
… with surface | 3,475 (66.3%) |
… with smoothness / incline / wheelchair | 73 (1.4%) / 11 (0.2%) / 6 (0.1%) |
footway=sidewalk ways / footway=crossing ways | 1,658 / 1,074 |
highway=crossing nodes / highway=steps ways | 1,684 / 246 |
Nodes with kerb / elevator nodes | 1,277 / 8 |
Imported graph (cmd/importer + verification SQL)
| Metric | Value |
|---|---|
| Ways → edges | 9,013 → 21,173 (36 degenerate stretches skipped) |
| Total length | 703.1 km (footway 313.1 km, service 153.8, residential 95.4) |
| Footway/path/pedestrian edges | 11,159; surface on 70.3% of edges, 68.7% of length |
| Edges with kerb info | 2,459 (lowered 2,251, flush 179, raised 19) |
| Nearest-edge check (Dana Porter Library) | 5 nearest edges at 14.5–19.0 m |
Map data © OpenStreetMap contributors (ODbL). Basemap by OpenFreeMap. Built as a 10-day solo project.