Milestone 1 — live web search: - mock/server.js: /search + /search-status proxy to the self-hosted SearXNG (third leg of the 3-source blend; engine endpoint stays server-side), /spatial + /spatial-status proxy to the spatial service - mock/app.js: background enrichment of suggestion cards — each candidate gets a web element (discovery cards + "you might like" rows) that is checked via SearXNG in the background (one in-flight query per place, 1 h TTL, failures retry in ~5 min) and APPENDS sourced facts with provenance URLs; never reorders/rewrites the plan. New LLM tools: web_search (cite URLs) and poi_near (PostGIS). Status badge gains 'web' / 'spatial'. - styles.css: .cc-web live-facts blocks, t-web verified chip Milestone 2 — PostGIS spatial DB (code complete; needs docker access to run — see spatial/README.md): - spatial/: docker-compose (postgis/postgis:16-3.4 + osm2pgsql:16 one-shot importer + spatiald), schema.sql (poi table w/ GIST index, spatial_extract bookkeeping, refresh_poi()), import.sh for the PBF extracts in ../osm, spatiald (Go, lib/pq): /health, /near (ST_DWithin), /nearest (KNN), /corridor (ST_Buffer along a route), with kind/name/extract/limit filters |
||
|---|---|---|
| .. | ||
| docker-compose.yml | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| import.sh | ||
| main.go | ||
| README.md | ||
| schema.sql | ||
spatial — PostGIS source of truth
Native spatial queries for the trip planner (DESIGN.md §Data: "PostGIS (Postgres) — import PBF via osm2pgsql; gives SQL spatial queries (radius, nearest, bbox)"). Replaces the flat-file/Overpass approximations.
Stack
| Piece | What it is |
|---|---|
docker-compose.yml |
postgis/postgis:16-3.4 (DB, port 5432) + one-shot osm2pgsql:16 importer + spatiald (query service, port 5005) |
schema.sql |
runs on first boot: poi table (named POIs as points, GIST index), spatial_extract bookkeeping, refresh_poi() |
import.sh |
loads a PBF from ../osm/ via osm2pgsql, refreshes poi |
main.go (spatiald) |
JSON query service over poi |
Dockerfile |
builds spatiald |
Prerequisites
- Docker with the current user in the
dockergroup (on this box: one-timesudo usermod -aG docker $USER, then re-login). - PBF extracts in
../osm/(already present:nh.osm.pbf,colombia.osm.pbf, US state extracts).
Usage
docker compose up -d postgis # first: runs schema.sql
./import.sh ../osm/nh.osm.pbf nh # load New England (default)
./import.sh ../osm/colombia.osm.pbf colombia
docker compose up -d spatiald # query service on :5005
The mock server (mock/server.js) proxies it: GET /spatial/* → :5005,
plus GET /spatial-status for the UI badge. When the service is up, the
chat assistant gains the poi_near tool automatically.
spatiald endpoints
All return {"count":N,"results":[{extract,osm_id,name,kind,opening_hours, fee,website,addr_city,dist_m},…]}. Common filters:
extract=nh— one loaded extractkind=amenity=restaurant— exact kind, orkind=restaurant(any family)name=café— ILIKE substringlimit=20(max 200)
| Endpoint | Query | SQL core |
|---|---|---|
GET /health |
— | extract bookkeeping |
GET /near |
lat,lng,r(m; default 500) |
ST_DWithin(geography, …, r) + KNN ordering |
GET /nearest |
lat,lng |
ORDER BY geom <-> point |
GET /corridor |
points=lng,lat;…, r |
ST_DWithin(geom::geography, ST_Buffer(line::geography, r)) |
Examples:
curl 'localhost:5005/near?lat=42.35&lng=-71.06&r=1000&kind=restaurant'
curl 'localhost:5005/nearest?lat=10.40&lng=-75.54&kind=tourism&limit=5'
curl 'localhost:5005/corridor?r=300&kind=fuel&points=-71.06,42.35;-71.07,42.36'
Data notes
poicovers every named node (or polygon way, via centroid) with anamenity/tourism/shop/leisure/historic/placetag — the kinds the planner asks about. Unnamed amenities (e.g. a nameless kiosk) are out of scope for v1.opening_hours,fee,website,addr_cityare carried straight from the OSM tags; the live web enrichment (SearXNG,mock/app.js) fills gaps the tags don't have (the 3-source blend).- Multiple extracts coexist in one DB, disambiguated by
poi.extract(set automatically byimport.sh). - pgvector (semantic POI index, later milestone) gets its own init script +
embedding importer — the base image doesn't ship the
vectorpackage.
Roadmap hooks
bboxqueries: trivial addition (ST_Contains(ST_MakeEnvelope,…)).- Routing-graph join: OSRM/GraphHopper geometries can be loaded into the
same DB (
route_geomtable) for true along-route analytics instead of the current buffer-over-polyline.