mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 13:26:42 +02:00
New mana-geocoding service (port 3018) wraps a self-hosted Pelias instance with LRU caching and OSM→PlaceCategory auto-mapping. All geocoding queries stay within our infrastructure — no user location data leaves the network. Places module integration: - Address autocomplete search in ListView (creates place with name, coords, address, category in one step) - Address search + reverse geocoding button in DetailView - Auto-fill address via reverse geocoding during tracking - OSM category mapping (amenity:restaurant→food, shop:*→shopping, etc.) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
148 lines
4.1 KiB
Markdown
148 lines
4.1 KiB
Markdown
# mana-geocoding
|
|
|
|
Self-hosted geocoding service. Wraps a local Pelias instance (DACH region) with caching and automatic OSM → PlaceCategory mapping. All geocoding queries stay within our infrastructure — no user location data leaves the network.
|
|
|
|
## Tech Stack
|
|
|
|
| Layer | Technology |
|
|
|-------|------------|
|
|
| **Runtime** | Bun |
|
|
| **Framework** | Hono |
|
|
| **Geocoding** | Pelias (self-hosted, Elasticsearch-backed) |
|
|
| **Data** | OpenStreetMap DACH extract (DE/AT/CH) |
|
|
| **Caching** | In-memory LRU (5000 entries, 24h TTL) |
|
|
|
|
## Port: 3018
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# 1. Start Pelias stack (first time: run setup.sh for data import)
|
|
cd services/mana-geocoding/pelias
|
|
docker compose up -d
|
|
# First time only:
|
|
chmod +x setup.sh && ./setup.sh
|
|
|
|
# 2. Start the Hono wrapper
|
|
cd services/mana-geocoding
|
|
bun run dev
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
All endpoints are public (no auth required) — the service is internal-only, not exposed to the internet.
|
|
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | `/api/v1/geocode/search?q=...` | Forward geocoding / autocomplete |
|
|
| GET | `/api/v1/geocode/reverse?lat=...&lon=...` | Reverse geocoding |
|
|
| GET | `/api/v1/geocode/stats` | Cache statistics |
|
|
| GET | `/health` | Health check |
|
|
|
|
### Search params
|
|
|
|
| Param | Required | Description |
|
|
|-------|----------|-------------|
|
|
| `q` | yes | Search query (min 2 chars) |
|
|
| `limit` | no | Max results (default 5, max 20) |
|
|
| `lang` | no | Language (default `de`) |
|
|
| `focus.lat` | no | Bias results towards this latitude |
|
|
| `focus.lon` | no | Bias results towards this longitude |
|
|
|
|
### Reverse params
|
|
|
|
| Param | Required | Description |
|
|
|-------|----------|-------------|
|
|
| `lat` | yes | Latitude |
|
|
| `lon` | yes | Longitude |
|
|
| `lang` | no | Language (default `de`) |
|
|
|
|
### Response format
|
|
|
|
```json
|
|
{
|
|
"results": [
|
|
{
|
|
"label": "Münster Café, Münsterplatz 3, 78462 Konstanz",
|
|
"name": "Münster Café",
|
|
"latitude": 47.663,
|
|
"longitude": 9.175,
|
|
"address": {
|
|
"street": "Münsterplatz",
|
|
"houseNumber": "3",
|
|
"postalCode": "78462",
|
|
"city": "Konstanz",
|
|
"country": "Germany"
|
|
},
|
|
"category": "food",
|
|
"osmCategory": "amenity",
|
|
"osmType": "cafe",
|
|
"confidence": 0.95
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Category Mapping
|
|
|
|
The service maps OSM tags to our 7 PlaceCategories:
|
|
|
|
| PlaceCategory | OSM examples |
|
|
|---------------|-------------|
|
|
| `home` | building:residential, building:house, building:apartments |
|
|
| `work` | amenity:school, amenity:university, office:*, building:commercial |
|
|
| `food` | amenity:restaurant, amenity:cafe, shop:bakery, shop:supermarket |
|
|
| `shopping` | shop:*, amenity:marketplace |
|
|
| `transit` | railway:station, highway:bus_stop, amenity:parking, aeroway:* |
|
|
| `leisure` | tourism:*, leisure:park, amenity:cinema, sport:* |
|
|
| `other` | Everything else |
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Client (Places module)
|
|
→ mana-geocoding (Hono, port 3018)
|
|
→ LRU cache check
|
|
→ Pelias API (port 4000)
|
|
→ Elasticsearch (port 9200)
|
|
```
|
|
|
|
## Configuration
|
|
|
|
```env
|
|
PORT=3018
|
|
PELIAS_API_URL=http://localhost:4000/v1
|
|
CORS_ORIGINS=http://localhost:5173,https://mana.how
|
|
CACHE_MAX_ENTRIES=5000
|
|
CACHE_TTL_MS=86400000
|
|
```
|
|
|
|
## Pelias Infrastructure
|
|
|
|
The Pelias stack runs as a separate docker-compose in `pelias/`:
|
|
|
|
- **elasticsearch** — Index storage (~500MB for DACH)
|
|
- **api** — HTTP API (port 4000)
|
|
- **libpostal** — Address parsing (port 4400)
|
|
- **Import containers** — Run once for initial data load, then stop
|
|
|
|
RAM usage (running): ~1.5GB (elasticsearch 512MB + api + libpostal)
|
|
|
|
## Code Layout
|
|
|
|
```
|
|
src/
|
|
├── index.ts # Bootstrap
|
|
├── app.ts # Hono app factory
|
|
├── config.ts # Environment config
|
|
├── routes/
|
|
│ ├── geocode.ts # Forward + reverse endpoints with caching
|
|
│ └── health.ts
|
|
└── lib/
|
|
├── cache.ts # LRU cache with TTL
|
|
└── category-map.ts # OSM → PlaceCategory mapping
|
|
pelias/
|
|
├── docker-compose.yml # Pelias stack
|
|
├── pelias.json # Pelias config (DACH region)
|
|
└── setup.sh # Initial data import script
|
|
```
|