A FastAPI-based backend for planning optimized visit routes from Google Maps saved lists. It scrapes, enriches, and manages places of interest, then feeds them into a route optimizer based on the Travelling Salesman Problem.
The purpose of this project is to transform a personal Google Maps saved list into an optimized visit schedule. The user imports locations, sets per-place scheduling preferences (preferred visit window, estimated duration), and the planner computes the most time-efficient visiting order using Google Maps Distance Matrix and TSP algorithms.
- Imports places from public Google Maps saved lists via Playwright scraper.
- Enriches place data (address, opening hours, coordinates) via Google Places API.
- Manages scheduling preferences per place: preferred visit window, duration, skip flag.
- REST API for full CRUD management of the location pool.
- Route optimization based on TSP with time window constraints (Nearest Neighbor + 2-opt, Google Routes API distance matrix).
- Docker deployment with MongoDB persistence.
- Python >=3.14
- uv package manager
- Docker Desktop / Docker + Compose
- Google Cloud API key with Places API (New) and Routes API enabled
Copy docker/.env.template to docker/.env and fill in the values:
| Variable | Required | Description |
|---|---|---|
MONGO_URI |
yes | MongoDB connection string |
MONGO_DB |
yes | Database name |
GOOGLE_PLACES_API_KEY |
yes | Google Cloud key — must have Places API (New) enabled |
GOOGLE_ROUTES_API_KEY |
yes | Google Cloud key — must have Routes API enabled (can be the same key) |
DEBUG |
no | Set to true to enable debug logging |
- Clone the repository:
git clone <repository-url>
- Set up the
.envfile based on the provided template:copy docker\.env.template docker\.env
- Run using Docker:
just up
The Docker stack runs MongoDB as a single-node replica set for transaction support.
The application connects from inside the Docker network via the service name mongo, but MongoDB Compass connects from the Windows host, so it should use:
mongodb://localhost:27017/?directConnection=true
If you omit directConnection=true, Compass may try to follow the replica set host mongo:27017, which is resolvable inside Docker but not from Windows.
- Clone the repository:
git clone <repository-url>
- Set up the
.envfile based on the provided template. - Install dependencies:
uv sync
- Run the application locally:
uv run uvicorn src.main:app --host 0.0.0.0 --port 8080 --reload
After step 4: Install dev dependencies and pre-commit hooks:
uv sync --group dev
uv run pre-commit install
uv run pre-commit run --all-files- Daily commits — stage your changes and use Commitizen for consistent messages:
git add <files> just commit
- Bump the application version on release branches:
just bump # auto-tags vX.Y.Z and updates pyproject.toml
Run unit and regression tests (no Docker required):
just testRun integration tests (requires Docker Desktop running):
just test-integrationRun the full linting suite (ruff format + check, ty, codespell):
just lint- FastAPI docs: fastapi.tiangolo.com
- Google Places API: developers.google.com
- Google Routes API: developers.google.com
- Pydantic AI docs: ai.pydantic.dev
- PyMongo docs: pymongo.readthedocs.io
- uv docs: docs.astral.sh/uv