# naina-sriv/routeiq architecture

> Architecture diagram of the GitHub repository naina-sriv/routeiq, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-25). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/naina-sriv/routeiq
- Repository: https://github.com/naina-sriv/routeiq

## Overview

1. **Overall shape**  
RouteIQ is a single Python backend with a browser-based, map-driven frontend. The core runtime is FastAPI in `routeiq/main.py`, which sits between the UI and the optimization services. The app solves two distinct problems: single-vehicle trip ordering (TSP) and multi-vehicle fleet routing with constraints (VRP).

2. **Frontend boundary**  
The browser UI is a single-page experience rendered from `templates/index.html` and powered by vanilla JS in `static/js/`. `app.js` owns shared map state, stop management, and geocoding interactions; `trip.js` handles trip-planner mode; `fleet.js` handles fleet mode, vehicle lists, and route rendering. Leaflet is the map layer, and the frontend talks to the backend only through HTTP `fetch()` calls.

3. **API layer**  
`main.py` exposes the service boundary: `GET /health`, `POST /optimize`, `POST /optimize/fleet`, `POST /geocode`, and `POST /reverse-geocode`. `models.py` defines the request/response contracts using Pydantic, while `config.py` centralizes environment-driven settings such as OSRM, Redis, stop limits, and solver timeouts.

4. **Trip optimization flow (TSP)**  
`POST /optimize` sends the stop list through a road-distance matrix lookup, then into `utils/solver.py`. That solver uses Google OR-Tools for a single-vehicle route with fixed start and end nodes. The output is an ordered stop sequence plus per-leg travel times and polylines; if OR-Tools fails or times out, it falls back to a nearest-neighbor route.

5. **Fleet optimization flow (VRP)**  
`POST /optimize/fleet` follows the same matrix acquisition path, then passes the data to `utils/vrp_solver.py`. This solver adds the fleet-specific constraints: one route per vehicle, vehicle capacity limits, optional per-stop time windows, and penalties for dropping stops when the fleet cannot cover everything. The response is grouped by vehicle and includes unassigned stops.

6. **Road-network dependency**  
`utils/osrm.py` is the road-travel layer. It queries OSRM’s `/table` endpoint for the travel-time matrix and `/route` for leg polylines. This is the main external dependency that gives the app real road times instead of straight-line estimates. If OSRM is unavailable, the system can fall back to haversine-based estimates, and the response marks that fallback.

7. **Caching boundary**  
`utils/cache.py` wraps Redis and caches the distance matrix, not the full optimization result. The cache key is derived from the stop coordinates in an order-independent way, so the same set of points reuses the same matrix even if the request order changes. This cache is the main performance boundary: it turns repeated route requests for the same stop set from OSRM-bound to near-instant.

8. **Geocoding path**  
`utils/geocoder.py` handles forward and reverse geocoding through Nominatim. This is a separate flow from routing: user-entered addresses become coordinates before optimization, and dragged map pins can be converted back into display names. It supports the map UX but does not affect the solver logic.

9. **Deployment topology**  
The repo is designed to run as a small containerized stack defined in `docker-compose.yml`: the FastAPI app, Redis, and an OSRM backend. In Docker, the app points to the internal OSRM service; outside Docker it can use a public OSRM endpoint. The OSRM container depends on preprocessed map data mounted into a volume, which is an operational prerequisite for routing.

10. **Supporting quality and analysis subsystems**  
`tests/` contains unit and integration coverage for the solvers and API behavior, especially route ordering, capacity limits, time windows, and error handling. `benchmarks/compare_algorithms.py` is a separate analysis tool that compares OR-Tools against a nearest-neighbor baseline using synthetic points and haversine distances. These are not part of the request path, but they validate solver quality and runtime claims.

Main entry points: [`routeiq/main.py`](https://github.com/naina-sriv/routeiq/blob/main/routeiq/main.py) (API server), [`routeiq/utils/osrm.py`](https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/osrm.py) (Road matrix), [`routeiq/static/js/app.js`](https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/js/app.js) (Shared map), [`routeiq/utils/solver.py`](https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/solver.py) (TSP solver)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Frontend"]
  node_templates_index["UI shell<br/>template<br/>[index.html]"]
  node_static_app["Shared map<br/>js app<br/>[app.js]"]
  node_static_trip["Trip mode<br/>js trip<br/>[trip.js]"]
  node_static_fleet["Fleet mode<br/>js fleet<br/>[fleet.js]"]
  node_static_css["Styles<br/>css<br/>[style.css]"]
end

subgraph group_backend["Backend"]
  node_main_api["API server<br/>fastapi<br/>[main.py]"]
  node_models["Contracts<br/>pydantic<br/>[models.py]"]
  node_config["Settings<br/>config<br/>[config.py]"]
  node_solver["TSP solver<br/>ortools tsp<br/>[solver.py]"]
  node_vrp_solver["VRP solver<br/>ortools vrp<br/>[vrp_solver.py]"]
  node_cache[("Matrix cache<br/>redis cache<br/>[cache.py]")]
end

subgraph group_external["External services"]
  node_osrm["Road matrix<br/>osrm client<br/>[osrm.py]"]
  node_geocoder["Geocoder<br/>nominatim client<br/>[geocoder.py]"]
end

subgraph group_ops["Ops"]
  node_docker_compose["Compose stack<br/>docker-compose<br/>[docker-compose.yml]"]
  node_dockerfile["App image<br/>dockerfile"]
end

subgraph group_quality["Quality"]
  node_benchmarks["Benchmark<br/>analysis script"]
  node_tests_api["API tests<br/>[test_api.py]"]
  node_tests_solver["Solver tests<br/>[test_solver.py]"]
  node_tests_vrp["VRP tests<br/>[test_vrp_solver.py]"]
end

node_templates_index -->|"loads"| node_static_app
node_static_app -->|"delegates"| node_static_trip
node_static_app -->|"delegates"| node_static_fleet
node_static_app -->|"fetch"| node_main_api
node_static_trip -->|"optimize"| node_main_api
node_static_fleet -->|"optimize fleet"| node_main_api
node_main_api -->|"uses"| node_models
node_main_api -->|"reads"| node_config
node_main_api -->|"matrix cache"| node_cache
node_main_api -->|"routes"| node_osrm
node_main_api -->|"geocodes"| node_geocoder
node_main_api -->|"trip flow"| node_solver
node_main_api -->|"fleet flow"| node_vrp_solver
node_solver -->|"depends on"| node_osrm
node_vrp_solver -->|"depends on"| node_osrm
node_cache -.->|"misses"| node_osrm
node_docker_compose -->|"runs"| node_main_api
node_docker_compose -->|"runs"| node_cache
node_docker_compose -->|"runs"| node_osrm
node_dockerfile -->|"builds"| node_main_api
node_tests_api -.->|"validates"| node_main_api
node_tests_solver -.->|"validates"| node_solver
node_tests_vrp -.->|"validates"| node_vrp_solver
node_benchmarks -.->|"compares"| node_solver
node_benchmarks -.->|"compares"| node_vrp_solver

click node_templates_index "https://github.com/naina-sriv/routeiq/blob/main/routeiq/templates/index.html"
click node_static_app "https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/js/app.js"
click node_static_trip "https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/js/trip.js"
click node_static_fleet "https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/js/fleet.js"
click node_static_css "https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/css/style.css"
click node_main_api "https://github.com/naina-sriv/routeiq/blob/main/routeiq/main.py"
click node_models "https://github.com/naina-sriv/routeiq/blob/main/routeiq/models.py"
click node_config "https://github.com/naina-sriv/routeiq/blob/main/routeiq/config.py"
click node_solver "https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/solver.py"
click node_vrp_solver "https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/vrp_solver.py"
click node_osrm "https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/osrm.py"
click node_cache "https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/cache.py"
click node_geocoder "https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/geocoder.py"
click node_docker_compose "https://github.com/naina-sriv/routeiq/blob/main/routeiq/docker-compose.yml"
click node_dockerfile "https://github.com/naina-sriv/routeiq/tree/main/routeiq/Dockerfile"
click node_benchmarks "https://github.com/naina-sriv/routeiq/blob/main/routeiq/benchmarks/compare_algorithms.py"
click node_tests_api "https://github.com/naina-sriv/routeiq/blob/main/routeiq/tests/test_api.py"
click node_tests_solver "https://github.com/naina-sriv/routeiq/blob/main/routeiq/tests/test_solver.py"
click node_tests_vrp "https://github.com/naina-sriv/routeiq/blob/main/routeiq/tests/test_vrp_solver.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_templates_index,node_static_app,node_static_trip,node_static_fleet,node_static_css toneBlue
class node_main_api,node_models,node_config,node_solver,node_vrp_solver,node_cache toneAmber
class node_osrm,node_geocoder toneMint
class node_docker_compose,node_dockerfile toneRose
class node_benchmarks,node_tests_api,node_tests_solver,node_tests_vrp toneIndigo
```

## Components

### Frontend

Browser UI, map state, and mode-specific interaction layers.

- [UI shell](https://github.com/naina-sriv/routeiq/blob/main/routeiq/templates/index.html): template · Single-page HTML entrypoint for the browser app. · `routeiq/templates/index.html`
- [Shared map](https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/js/app.js): js app · Owns shared map state, stop management, and geocoding interactions. · `routeiq/static/js/app.js`
- [Trip mode](https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/js/trip.js): js trip · Trip-planner interactions and route display for single-vehicle routing. · `routeiq/static/js/trip.js`
- [Fleet mode](https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/js/fleet.js): js fleet · Fleet-routing UI, vehicle lists, and multi-route rendering. · `routeiq/static/js/fleet.js`
- [Styles](https://github.com/naina-sriv/routeiq/blob/main/routeiq/static/css/style.css): css · Visual styling for the browser experience. · `routeiq/static/css/style.css`

### Backend

FastAPI service, request models, settings, and optimization pipeline.

- [API server](https://github.com/naina-sriv/routeiq/blob/main/routeiq/main.py): fastapi · HTTP boundary exposing health, optimization, geocoding, and reverse-geocoding endpoints. · `routeiq/main.py`
- [Contracts](https://github.com/naina-sriv/routeiq/blob/main/routeiq/models.py): pydantic · Request and response schemas for the API. · `routeiq/models.py`
- [Settings](https://github.com/naina-sriv/routeiq/blob/main/routeiq/config.py): config · Environment-driven settings for OSRM, Redis, limits, and solver timeouts. · `routeiq/config.py`
- [TSP solver](https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/solver.py): ortools tsp · Single-vehicle route optimizer with fallback ordering. · `routeiq/utils/solver.py`
- [VRP solver](https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/vrp_solver.py): ortools vrp · Multi-vehicle optimizer with capacity, time windows, and drop penalties. · `routeiq/utils/vrp_solver.py`
- [Matrix cache](https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/cache.py): redis cache · Caches distance matrices keyed by coordinate sets. · `routeiq/utils/cache.py`

### External services

Third-party and runtime dependencies used by the app.

- [Road matrix](https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/osrm.py): osrm client · Queries OSRM table and route endpoints for travel times and polylines. · `routeiq/utils/osrm.py`
- [Geocoder](https://github.com/naina-sriv/routeiq/blob/main/routeiq/utils/geocoder.py): nominatim client · Forward and reverse geocoding for addresses and map pins. · `routeiq/utils/geocoder.py`

### Ops

Container and deployment topology.

- [Compose stack](https://github.com/naina-sriv/routeiq/blob/main/routeiq/docker-compose.yml): docker-compose · Defines the app, Redis, and OSRM service topology. · `routeiq/docker-compose.yml`
- [App image](https://github.com/naina-sriv/routeiq/tree/main/routeiq/Dockerfile): dockerfile · Container build for the FastAPI application. · `routeiq/Dockerfile`

### Quality

Tests and benchmarking support.

- [Benchmark](https://github.com/naina-sriv/routeiq/blob/main/routeiq/benchmarks/compare_algorithms.py): analysis script · Compares OR-Tools against a nearest-neighbor baseline. · `routeiq/benchmarks/compare_algorithms.py`
- [API tests](https://github.com/naina-sriv/routeiq/blob/main/routeiq/tests/test_api.py): tests · Coverage for HTTP behavior and endpoint contracts. · `routeiq/tests/test_api.py`
- [Solver tests](https://github.com/naina-sriv/routeiq/blob/main/routeiq/tests/test_solver.py): tests · Coverage for trip ordering and solver behavior. · `routeiq/tests/test_solver.py`
- [VRP tests](https://github.com/naina-sriv/routeiq/blob/main/routeiq/tests/test_vrp_solver.py): tests · Coverage for fleet constraints and unassigned stops. · `routeiq/tests/test_vrp_solver.py`

## Connections

- UI shell → Shared map: loads · The page shell bootstraps shared frontend state.
- Shared map → Trip mode: delegates · Trip mode builds on the shared map and stop state.
- Shared map → Fleet mode: delegates · Fleet mode builds on the shared map and stop state.
- Shared map → API server: fetch · Frontend calls backend HTTP endpoints for optimization and geocoding.
- Trip mode → API server: optimize · Trip planner submits stops to the single-route endpoint.
- Fleet mode → API server: optimize fleet · Fleet UI submits vehicles and stops to the VRP endpoint.
- API server → Contracts: uses · API handlers serialize and validate with Pydantic schemas.
- API server → Settings: reads · Service behavior is driven by environment settings.
- API server → Matrix cache: matrix cache · Optimization requests reuse cached distance matrices when possible.
- API server → Road matrix: routes · Service fetches road-time matrices and route polylines.
- API server → Geocoder: geocodes · API exposes address lookup and reverse lookup endpoints.
- API server → TSP solver: trip flow · Single-vehicle optimization is delegated to the TSP solver.
- API server → VRP solver: fleet flow · Multi-vehicle optimization is delegated to the VRP solver.
- TSP solver → Road matrix: depends on · Trip optimization uses road-time matrices and leg polylines.
- VRP solver → Road matrix: depends on · Fleet optimization uses road-time matrices and leg polylines.
- Matrix cache → Road matrix: misses · Cache misses trigger fresh OSRM matrix requests.
- Compose stack → API server: runs · Compose brings up the application service.
- Compose stack → Matrix cache: runs · Compose includes Redis for matrix caching.
- Compose stack → Road matrix: runs · Compose includes the routing backend service.
- App image → API server: builds · The application image packages the FastAPI backend.
- API tests → API server: validates · API tests exercise endpoint behavior and error handling.
- Solver tests → TSP solver: validates · Solver tests cover trip ordering and fallback behavior.
- VRP tests → VRP solver: validates · VRP tests cover constraints and assignment outcomes.
- Benchmark → TSP solver: compares · Benchmark script compares the solver against a baseline.
- Benchmark → VRP solver: compares · Benchmark script can be extended to fleet-style comparisons.
