# saptadip/addrlens architecture

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

- Interactive diagram: https://gitdiagram.com/saptadip/addrlens
- Repository: https://github.com/saptadip/addrlens

## Overview

AddrLens helps renters evaluate a Berlin or Hamburg address using open-data neighbourhood facts, curated Life Mode lenses, raw dataset views, comparisons, and optional AI-written insights. The main workflow runs from address entry through lookup and data presentation; lens scoring and inference are distinct stages. The graph preserves documented capabilities, but sampled excerpts do not establish every route-to-core call or browser API endpoint, so uncertain links are omitted or marked unverified.

Main entry points: [`v0.1/app/main.py`](https://github.com/saptadip/addrlens/blob/main/v0.1/app/main.py) (FastAPI application), [`v0.1/web/static/app.js`](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/app.js) (Web bootstrap), [`v0.1/app/core/index.py`](https://github.com/saptadip/addrlens/blob/main/v0.1/app/core/index.py) (City data index), [`v0.1/inference/main.py`](https://github.com/saptadip/addrlens/blob/main/v0.1/inference/main.py) (Inference service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web experience"]
  node_frontend["Web bootstrap<br/>[app.js]"]
  node_browser_state["Browser state<br/>[state.js]"]
  node_web_api["API client<br/>[api.js]"]
  node_results["Dataset panels<br/>[amenities.js]"]
  node_environment["Environment panels<br/>[environment.js]"]
  node_connectivity["Connectivity panels<br/>[connectivity.js]"]
  node_maps["Maps<br/>[maps.js]"]
  node_life_mode["Life Mode lenses<br/>[index.js]"]
  node_compare["Address compare<br/>[compare.js]"]
end

subgraph group_app["City analysis"]
  node_city_config["City configuration<br/>[base.py]"]
  node_api_app["FastAPI application<br/>[main.py]"]
  node_lookup["Address lookup<br/>[lookup.py]"]
  node_amenities_route["Amenity routes<br/>[amenities.py]"]
  node_noise_route["Noise route<br/>[noise.py]"]
  node_lens_route["Lens insight route<br/>[lens_insight.py]"]
  node_data_index[("City data index<br/>[index.py]")]
  node_lens_scoring["Lens scoring<br/>[tiers.py]"]
  node_newcomer_lens["Newcomer lens logic<br/>[newcomer.py]"]
end

subgraph group_inference["AI insights"]
  node_inference_service["Inference service<br/>[main.py]"]
  node_local_backend["Local model backends<br/>[llama_backend.py]"]
  node_remote_backend["Cloudflare backend"]
  node_berlin_template["Berlin insight template"]
  node_hamburg_template["Hamburg insight template"]
end

subgraph group_sources["Open data"]
  node_open_datasets["Open datasets"]
  node_geoportal["Berlin Geoportal"]
  node_osm["OpenStreetMap"]
  node_transit["VBB / BVG"]
end

node_renter(("Renter"))

node_renter -->|"enters address"| node_frontend
node_frontend -->|"uses state"| node_browser_state
node_frontend -->|"invokes client"| node_web_api
node_web_api -->|"reads and updates"| node_browser_state
node_web_api -->|"supplies data"| node_results
node_results -->|"draws maps"| node_maps
node_frontend -->|"initializes lenses"| node_life_mode
node_life_mode -->|"updates map pins"| node_maps
node_frontend -->|"initializes compare"| node_compare
node_compare -->|"renders lens comparison"| node_life_mode
node_compare -->|"uses environment tiers"| node_environment
node_api_app -->|"registers route"| node_lookup
node_api_app -->|"registers route"| node_amenities_route
node_api_app -->|"registers route"| node_noise_route
node_api_app -->|"registers route"| node_lens_route
node_api_app -->|"loads at startup"| node_data_index
node_data_index -->|"uses city settings"| node_city_config
node_data_index -->|"loads spatial data"| node_geoportal
node_data_index -->|"uses OSM data"| node_osm
node_data_index -->|"uses transit data"| node_transit
node_renter -.->|"receives address insights"| node_open_datasets
node_life_mode -.->|"shows tiered results"| node_lens_scoring
node_newcomer_lens -->|"uses scoring rules"| node_lens_scoring
node_lens_route -->|"requests insight"| node_inference_service
node_inference_service -->|"selects local backend"| node_local_backend
node_inference_service -->|"configures remote backend"| node_remote_backend
node_inference_service -->|"registers templates"| node_berlin_template
node_inference_service -->|"registers templates"| node_hamburg_template
node_lens_route -.->|"returns lens insight"| node_life_mode

click node_frontend "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/app.js"
click node_browser_state "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/state.js"
click node_web_api "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/api.js"
click node_results "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/panels/amenities.js"
click node_environment "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/panels/environment.js"
click node_connectivity "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/panels/connectivity.js"
click node_maps "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/maps.js"
click node_life_mode "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/lens/index.js"
click node_compare "https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/compare.js"
click node_city_config "https://github.com/saptadip/addrlens/blob/main/v0.1/app/cities/base.py"
click node_api_app "https://github.com/saptadip/addrlens/blob/main/v0.1/app/main.py"
click node_lookup "https://github.com/saptadip/addrlens/blob/main/v0.1/app/routes/lookup.py"
click node_amenities_route "https://github.com/saptadip/addrlens/blob/main/v0.1/app/routes/amenities.py"
click node_noise_route "https://github.com/saptadip/addrlens/blob/main/v0.1/app/routes/noise.py"
click node_lens_route "https://github.com/saptadip/addrlens/blob/main/v0.1/app/routes/lens_insight.py"
click node_data_index "https://github.com/saptadip/addrlens/blob/main/v0.1/app/core/index.py"
click node_lens_scoring "https://github.com/saptadip/addrlens/blob/main/v0.1/app/core/scoring/tiers.py"
click node_newcomer_lens "https://github.com/saptadip/addrlens/blob/main/v0.1/app/core/lenses/newcomer.py"
click node_inference_service "https://github.com/saptadip/addrlens/blob/main/v0.1/inference/main.py"
click node_local_backend "https://github.com/saptadip/addrlens/blob/main/v0.1/inference/runtime/llama_backend.py"
click node_remote_backend "https://github.com/saptadip/addrlens/blob/main/v0.1/inference/runtime/cloudflare_backend.py"
click node_berlin_template "https://github.com/saptadip/addrlens/blob/main/v0.1/inference/templates/lens_newcomer_insight.py"
click node_hamburg_template "https://github.com/saptadip/addrlens/blob/main/v0.1/inference/templates/lens_newcomer_hamburg_insight.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_frontend,node_browser_state,node_web_api,node_results,node_environment,node_connectivity,node_maps,node_life_mode,node_compare toneBlue
class node_city_config,node_api_app,node_lookup,node_amenities_route,node_noise_route,node_lens_route,node_data_index,node_lens_scoring,node_newcomer_lens toneAmber
class node_inference_service,node_local_backend,node_remote_backend,node_berlin_template,node_hamburg_template toneMint
class node_open_datasets,node_geoportal,node_osm,node_transit toneRose
class node_renter toneIndigo
```

## Components

### Web experience

- [Web bootstrap](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/app.js): `v0.1/web/static/app.js`
- [Browser state](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/state.js): `v0.1/web/static/modules/state.js`
- [API client](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/api.js): `v0.1/web/static/modules/api.js`
- [Dataset panels](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/panels/amenities.js): `v0.1/web/static/modules/panels/amenities.js`
- [Environment panels](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/panels/environment.js): `v0.1/web/static/modules/panels/environment.js`
- [Connectivity panels](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/panels/connectivity.js): `v0.1/web/static/modules/panels/connectivity.js`
- [Maps](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/maps.js): `v0.1/web/static/modules/maps.js`
- [Life Mode lenses](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/lens/index.js): `v0.1/web/static/modules/lens/index.js`
- [Address compare](https://github.com/saptadip/addrlens/blob/main/v0.1/web/static/modules/compare.js): `v0.1/web/static/modules/compare.js`

### City analysis

- [City configuration](https://github.com/saptadip/addrlens/blob/main/v0.1/app/cities/base.py): `v0.1/app/cities/base.py`
- [FastAPI application](https://github.com/saptadip/addrlens/blob/main/v0.1/app/main.py): `v0.1/app/main.py`
- [Address lookup](https://github.com/saptadip/addrlens/blob/main/v0.1/app/routes/lookup.py): `v0.1/app/routes/lookup.py`
- [Amenity routes](https://github.com/saptadip/addrlens/blob/main/v0.1/app/routes/amenities.py): `v0.1/app/routes/amenities.py`
- [Noise route](https://github.com/saptadip/addrlens/blob/main/v0.1/app/routes/noise.py): `v0.1/app/routes/noise.py`
- [Lens insight route](https://github.com/saptadip/addrlens/blob/main/v0.1/app/routes/lens_insight.py): `v0.1/app/routes/lens_insight.py`
- [City data index](https://github.com/saptadip/addrlens/blob/main/v0.1/app/core/index.py): `v0.1/app/core/index.py`
- [Lens scoring](https://github.com/saptadip/addrlens/blob/main/v0.1/app/core/scoring/tiers.py): `v0.1/app/core/scoring/tiers.py`
- [Newcomer lens logic](https://github.com/saptadip/addrlens/blob/main/v0.1/app/core/lenses/newcomer.py): `v0.1/app/core/lenses/newcomer.py`

### AI insights

- [Inference service](https://github.com/saptadip/addrlens/blob/main/v0.1/inference/main.py): `v0.1/inference/main.py`
- [Local model backends](https://github.com/saptadip/addrlens/blob/main/v0.1/inference/runtime/llama_backend.py): `v0.1/inference/runtime/llama_backend.py`
- [Cloudflare backend](https://github.com/saptadip/addrlens/blob/main/v0.1/inference/runtime/cloudflare_backend.py): `v0.1/inference/runtime/cloudflare_backend.py`
- [Berlin insight template](https://github.com/saptadip/addrlens/blob/main/v0.1/inference/templates/lens_newcomer_insight.py): `v0.1/inference/templates/lens_newcomer_insight.py`
- [Hamburg insight template](https://github.com/saptadip/addrlens/blob/main/v0.1/inference/templates/lens_newcomer_hamburg_insight.py): `v0.1/inference/templates/lens_newcomer_hamburg_insight.py`

### Open data

- **Open datasets**
- **Berlin Geoportal**
- **OpenStreetMap**
- **VBB / BVG**

### Other components

- **Renter**

## Connections

- Renter → Web bootstrap: enters address (evidence: `README.md`)
- Web bootstrap → Browser state: uses state (evidence: `v0.1/web/static/app.js`)
- Web bootstrap → API client: invokes client (evidence: `v0.1/web/static/app.js`)
- API client → Browser state: reads and updates (evidence: `v0.1/web/static/modules/api.js`)
- API client → Dataset panels: supplies data (evidence: `v0.1/web/static/modules/api.js`)
- Dataset panels → Maps: draws maps (evidence: `v0.1/web/static/modules/panels/amenities.js`)
- Web bootstrap → Life Mode lenses: initializes lenses (evidence: `v0.1/web/static/app.js`)
- Life Mode lenses → Maps: updates map pins (evidence: `v0.1/web/static/modules/lens/index.js`)
- Web bootstrap → Address compare: initializes compare (evidence: `v0.1/web/static/app.js`)
- Address compare → Life Mode lenses: renders lens comparison (evidence: `v0.1/web/static/modules/compare.js`)
- Address compare → Environment panels: uses environment tiers (evidence: `v0.1/web/static/modules/compare.js`)
- FastAPI application → Address lookup: registers route (evidence: `v0.1/app/main.py`)
- FastAPI application → Amenity routes: registers route (evidence: `v0.1/app/main.py`)
- FastAPI application → Noise route: registers route (evidence: `v0.1/app/main.py`)
- FastAPI application → Lens insight route: registers route (evidence: `v0.1/app/main.py`)
- FastAPI application → City data index: loads at startup (evidence: `v0.1/app/core/index.py`)
- City data index → City configuration: uses city settings (evidence: `v0.1/app/core/index.py`)
- City data index → Berlin Geoportal: loads spatial data (evidence: `README.md`)
- City data index → OpenStreetMap: uses OSM data (evidence: `README.md`)
- City data index → VBB / BVG: uses transit data (evidence: `README.md`)
- Renter → Open datasets: receives address insights (evidence: `README.md`)
- Life Mode lenses → Lens scoring: shows tiered results (evidence: `README.md`)
- Newcomer lens logic → Lens scoring: uses scoring rules (evidence: `v0.1/app/core/lenses/newcomer.py`)
- Lens insight route → Inference service: requests insight (evidence: `v0.1/app/routes/lens_insight.py`)
- Inference service → Local model backends: selects local backend (evidence: `v0.1/inference/main.py`)
- Inference service → Cloudflare backend: configures remote backend (evidence: `v0.1/inference/main.py`)
- Inference service → Berlin insight template: registers templates (evidence: `v0.1/inference/main.py`)
- Inference service → Hamburg insight template: registers templates (evidence: `v0.1/inference/main.py`)
- Lens insight route → Life Mode lenses: returns lens insight
