sync: 2026-08-21 15:04:46
This commit is contained in:
84
README.md
Normal file
84
README.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# LibreMaps
|
||||
|
||||
A lightweight, self-hosted map viewer built with **Flask** and **Leaflet**, powered entirely by free open data from **OpenStreetMap** (via the Nominatim geocoding API) and **MapTiler** street tiles.
|
||||
|
||||
## Features
|
||||
|
||||
- **Interactive map** — pan/zoom over MapTiler "Streets" tiles, centered on Amsterdam by default.
|
||||
- **Search** — type a place or POI to search. Results are first restricted to the area currently visible on the map; if nothing is found locally, it automatically falls back to searching the entire world.
|
||||
- **Category shortcuts** — quick chips for common places (Supermarkt, Café, Kroeg, Camping, Park, Restaurant, Vegan, Hotel, Parkeerplek).
|
||||
- **Typed pins** — each result is drawn as a colored circular badge whose emoji and color reflect the POI type (e.g. 🍴 orange for food, 🛏 purple for hotels, 🚆 blue for transport, 💊 red for pharmacies, 🌳 green for parks). A small permanent label shows the location name above each pin.
|
||||
- **Place details card** — click a result or a pin to see the name, type, address, opening hours, phone, website, email, and extra tags (cuisine, brand, wheelchair access, payment methods, etc.).
|
||||
- **Actions** — get directions (Google Maps), web search (Qwant), call, visit website, or email directly from the detail card.
|
||||
- **Reverse geocoding** — click anywhere on the map (when zoomed in enough) to look up what's at that spot.
|
||||
- **"My location"** button using browser geolocation.
|
||||
- **Responsive layout** — adapts to mobile screens.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|-----------|-------------------------------------|
|
||||
| Backend | Python 3, Flask |
|
||||
| Frontend | Vanilla JS, Leaflet 1.9.4 |
|
||||
| Geocoding | OpenStreetMap Nominatim |
|
||||
| Tiles | MapTiler Streets v4 |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
openmaps/
|
||||
├── app.py # Flask app: /, /search, /geocode routes
|
||||
├── templates/
|
||||
│ └── index.html # Single-page UI (map + all client logic)
|
||||
├── sync.py # Sync helper script
|
||||
├── requirements.txt # Python dependencies
|
||||
├── Dockerfile # Container image definition
|
||||
├── docker-compose.yml # Local container orchestration
|
||||
├── .dockerignore
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
### Backend (`app.py`)
|
||||
|
||||
Three endpoints proxy requests to Nominatim while applying a simple rate limit (minimum 1 second between calls) and a descriptive `User-Agent`:
|
||||
|
||||
- `GET /` — serves the single-page UI.
|
||||
- `GET /search?q=...&viewbox=left,top,right,bottom` — forwards a forward-geocoding query. When a valid viewbox is supplied, results are bounded to that region (`bounded=1`). Returns normalized JSON (coordinates, address, extratags, namedetails, importance, bounding box).
|
||||
- `GET /geocode?lat=...&lon=...` — reverse-geocodes a coordinate into a place record.
|
||||
|
||||
### Frontend (`templates/index.html`)
|
||||
|
||||
- Initializes a Leaflet map with MapTiler tiles.
|
||||
- Builds a viewbox from the current map bounds and sends it with each search so results stay local.
|
||||
- Renders results in a scrollable card and drops typed pins on the map.
|
||||
- Falls back to a worldwide search when the local search returns nothing.
|
||||
- Shows a detail card with contact info, opening hours, and action buttons.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Python 3.x
|
||||
- (Optional) Docker / Docker Compose
|
||||
|
||||
### Run locally
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
python app.py
|
||||
```
|
||||
|
||||
Then open <http://localhost:5000>.
|
||||
|
||||
### Run with Docker
|
||||
|
||||
```bash
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The MapTiler tile layer uses an embedded API key in `templates/index.html`; replace it with your own key for production use.
|
||||
- Nominatim has usage policies — keep the built-in rate limiting in place and identify your application via the `User-Agent`.
|
||||
Reference in New Issue
Block a user