# thelemoh/digital-twin architecture

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

- Interactive diagram: https://gitdiagram.com/thelemoh/digital-twin
- Repository: https://github.com/thelemoh/digital-twin

## Overview

This is a Nuxt-based environmental digital-twin application centered on viewing monitoring sites and model data on a map over a selected date range. The main workflow loads and filters site observations, derives map features and averages, and presents them alongside indicator, timeline, and site-detail views. Separate map layers support raster and terrain visualization; profiler and weather-model dialogs form additional analysis branches. The README is only a Nuxt starter, and sampled source does not establish wiring for every listed subsystem, so uncertain links are omitted.

Main entry points: [`app/pages/index.vue`](https://github.com/thelemoh/digital-twin/blob/main/app/pages/index.vue) (Map page), [`app/composables/useSite.ts`](https://github.com/thelemoh/digital-twin/blob/main/app/composables/useSite.ts) (Site data workflow), [`app/components/Map/composables/useTwinTiles.js`](https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useTwinTiles.js) (Twin raster), [`app/core/data/dataService.ts`](https://github.com/thelemoh/digital-twin/blob/main/app/core/data/dataService.ts) (Observation data service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["Application shell"]
  node_page["Map page<br/>[index.vue]"]
  node_app_shell["App state<br/>[app.vue]"]
  node_indicators_ui["Indicators<br/>[Indicators.vue]"]
  node_timeline_ui["Timeline<br/>[Timeline.vue]"]
  node_list_page["Site list page<br/>[list.vue]"]
end

subgraph group_observations["Site observations"]
  node_site_loader["Site data workflow<br/>[useSite.ts]"]
  node_data_register["Data service registration<br/>[register.ts]"]
  node_data_service["Observation data service<br/>[dataService.ts]"]
  node_site_features["Site features"]
  node_site_filters["Site filters<br/>[siteFilter.ts]"]
end

subgraph group_mapping["Map visualization"]
  node_map_view["Map view<br/>[Map.vue]"]
  node_map_init["Map setup<br/>[useMap.ts]"]
  node_site_layer["Site layer<br/>[useSiteLayer.ts]"]
  node_polygon_layers["Polygon layers"]
  node_terrain_layer["Terrain layer<br/>[useTerrain.ts]"]
  node_deck_layer["DeckGL layer<br/>[useDeckGL.js]"]
  node_twin_tiles["Twin raster<br/>[useTwinTiles.js]"]
  node_tiff_parser["TIFF parser<br/>[parseTiff.js]"]
end

subgraph group_analysis["Analysis tools"]
  node_averages["Observation averages<br/>[avg.ts]"]
  node_site_dialog["Site detail dialog<br/>[useSiteDialog.ts]"]
  node_profiler["Profiler analysis"]
  node_profiler_service["Profiler data service"]
  node_weather_dialog["GFS dialog<br/>[useDialog.js]"]
  node_wind_calc["Wind calculation<br/>[calculateWind.ts]"]
  node_calculations["Calculations UI"]
end

node_user(("User"))
node_raster_service["Raster service"]
node_sensor_api["Sensor API"]

node_user -->|"opens"| node_page
node_page -->|"uses shared state"| node_app_shell
node_page -->|"loads site data"| node_site_loader
node_site_loader -->|"uses service"| node_data_register
node_data_register -->|"provides"| node_data_service
node_data_service -->|"fetches observations"| node_sensor_api
node_sensor_api -->|"returns observations"| node_data_service
node_site_loader -->|"filters sites"| node_site_filters
node_site_loader -->|"builds features"| node_site_features
node_site_loader -->|"computes averages"| node_averages
node_page -->|"renders"| node_map_view
node_page -->|"initializes map"| node_map_init
node_page -->|"sets up layer"| node_site_layer
node_page -->|"sets up layers"| node_polygon_layers
node_page -->|"sets up layer"| node_terrain_layer
node_page -->|"sets up layer"| node_deck_layer
node_page -->|"sets up raster"| node_twin_tiles
node_twin_tiles -->|"fetches TIFF"| node_raster_service
node_twin_tiles -->|"parses TIFF"| node_tiff_parser
node_page -->|"renders"| node_indicators_ui
node_page -->|"renders"| node_timeline_ui
node_page -->|"renders when selected"| node_site_dialog
node_page -->|"renders profiler"| node_profiler
node_profiler -->|"loads profiler data"| node_profiler_service
node_page -->|"hosts dialog"| node_weather_dialog
node_weather_dialog -->|"calculates wind"| node_wind_calc
node_page -->|"renders"| node_calculations
node_page -->|"links to list view"| node_list_page

click node_page "https://github.com/thelemoh/digital-twin/blob/main/app/pages/index.vue"
click node_app_shell "https://github.com/thelemoh/digital-twin/blob/main/app/app.vue"
click node_map_view "https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/components/Map.vue"
click node_map_init "https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useMap.ts"
click node_site_layer "https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useSiteLayer.ts"
click node_terrain_layer "https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useTerrain.ts"
click node_deck_layer "https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useDeckGL.js"
click node_twin_tiles "https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useTwinTiles.js"
click node_tiff_parser "https://github.com/thelemoh/digital-twin/blob/main/app/core/tiff/parseTiff.js"
click node_site_loader "https://github.com/thelemoh/digital-twin/blob/main/app/composables/useSite.ts"
click node_data_register "https://github.com/thelemoh/digital-twin/blob/main/app/core/data/register.ts"
click node_data_service "https://github.com/thelemoh/digital-twin/blob/main/app/core/data/dataService.ts"
click node_site_features "https://github.com/thelemoh/digital-twin/blob/main/app/core/features/createSiteFeature.ts"
click node_site_filters "https://github.com/thelemoh/digital-twin/blob/main/app/core/filters/siteFilter.ts"
click node_averages "https://github.com/thelemoh/digital-twin/blob/main/app/core/avg/avg.ts"
click node_indicators_ui "https://github.com/thelemoh/digital-twin/blob/main/app/components/Indicator/components/Indicators.vue"
click node_timeline_ui "https://github.com/thelemoh/digital-twin/blob/main/app/components/Timeline/components/Timeline.vue"
click node_site_dialog "https://github.com/thelemoh/digital-twin/blob/main/app/components/SiteDialog/composables/useSiteDialog.ts"
click node_profiler "https://github.com/thelemoh/digital-twin/blob/main/app/components/ProfilerDialog/composables/useProfilerDialog.ts"
click node_profiler_service "https://github.com/thelemoh/digital-twin/blob/main/app/core/data/registerProfiler.ts"
click node_weather_dialog "https://github.com/thelemoh/digital-twin/blob/main/app/components/Dialog/composables/useDialog.js"
click node_wind_calc "https://github.com/thelemoh/digital-twin/blob/main/app/core/wind/calculateWind.ts"
click node_calculations "https://github.com/thelemoh/digital-twin/blob/main/app/components/%D0%A1alculations/components/BodyCalculation.vue"
click node_list_page "https://github.com/thelemoh/digital-twin/blob/main/app/pages/list.vue"

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_page,node_app_shell,node_indicators_ui,node_timeline_ui,node_list_page,node_user toneBlue
class node_site_loader,node_data_register,node_data_service,node_site_features,node_site_filters toneAmber
class node_map_view,node_map_init,node_site_layer,node_polygon_layers,node_terrain_layer,node_deck_layer,node_twin_tiles,node_tiff_parser,node_sensor_api toneMint
class node_averages,node_site_dialog,node_profiler,node_profiler_service,node_weather_dialog,node_wind_calc,node_calculations toneRose
class node_raster_service toneIndigo
```

## Components

### Application shell

- [Map page](https://github.com/thelemoh/digital-twin/blob/main/app/pages/index.vue): `app/pages/index.vue`
- [App state](https://github.com/thelemoh/digital-twin/blob/main/app/app.vue): `app/app.vue`
- [Indicators](https://github.com/thelemoh/digital-twin/blob/main/app/components/Indicator/components/Indicators.vue): `app/components/Indicator/components/Indicators.vue`
- [Timeline](https://github.com/thelemoh/digital-twin/blob/main/app/components/Timeline/components/Timeline.vue): `app/components/Timeline/components/Timeline.vue`
- [Site list page](https://github.com/thelemoh/digital-twin/blob/main/app/pages/list.vue): `app/pages/list.vue`

### Site observations

- [Site data workflow](https://github.com/thelemoh/digital-twin/blob/main/app/composables/useSite.ts): `app/composables/useSite.ts`
- [Data service registration](https://github.com/thelemoh/digital-twin/blob/main/app/core/data/register.ts): `app/core/data/register.ts`
- [Observation data service](https://github.com/thelemoh/digital-twin/blob/main/app/core/data/dataService.ts): `app/core/data/dataService.ts`
- [Site features](https://github.com/thelemoh/digital-twin/blob/main/app/core/features/createSiteFeature.ts): `app/core/features/createSiteFeature.ts`
- [Site filters](https://github.com/thelemoh/digital-twin/blob/main/app/core/filters/siteFilter.ts): `app/core/filters/siteFilter.ts`

### Map visualization

- [Map view](https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/components/Map.vue): `app/components/Map/components/Map.vue`
- [Map setup](https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useMap.ts): `app/components/Map/composables/useMap.ts`
- [Site layer](https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useSiteLayer.ts): `app/components/Map/composables/useSiteLayer.ts`
- **Polygon layers**
- [Terrain layer](https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useTerrain.ts): `app/components/Map/composables/useTerrain.ts`
- [DeckGL layer](https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useDeckGL.js): `app/components/Map/composables/useDeckGL.js`
- [Twin raster](https://github.com/thelemoh/digital-twin/blob/main/app/components/Map/composables/useTwinTiles.js): `app/components/Map/composables/useTwinTiles.js`
- [TIFF parser](https://github.com/thelemoh/digital-twin/blob/main/app/core/tiff/parseTiff.js): `app/core/tiff/parseTiff.js`

### Analysis tools

- [Observation averages](https://github.com/thelemoh/digital-twin/blob/main/app/core/avg/avg.ts): `app/core/avg/avg.ts`
- [Site detail dialog](https://github.com/thelemoh/digital-twin/blob/main/app/components/SiteDialog/composables/useSiteDialog.ts): `app/components/SiteDialog/composables/useSiteDialog.ts`
- [Profiler analysis](https://github.com/thelemoh/digital-twin/blob/main/app/components/ProfilerDialog/composables/useProfilerDialog.ts): `app/components/ProfilerDialog/composables/useProfilerDialog.ts`
- [Profiler data service](https://github.com/thelemoh/digital-twin/blob/main/app/core/data/registerProfiler.ts): `app/core/data/registerProfiler.ts`
- [GFS dialog](https://github.com/thelemoh/digital-twin/blob/main/app/components/Dialog/composables/useDialog.js): `app/components/Dialog/composables/useDialog.js`
- [Wind calculation](https://github.com/thelemoh/digital-twin/blob/main/app/core/wind/calculateWind.ts): `app/core/wind/calculateWind.ts`
- [Calculations UI](https://github.com/thelemoh/digital-twin/blob/main/app/components/%D0%A1alculations/components/BodyCalculation.vue): `app/components/Сalculations/components/BodyCalculation.vue`

### Other components

- **User**
- **Raster service**
- **Sensor API**

## Connections

- User → Map page: opens
- Map page → App state: uses shared state
- Map page → Site data workflow: loads site data
- Site data workflow → Data service registration: uses service
- Data service registration → Observation data service: provides
- Observation data service → Sensor API: fetches observations
- Sensor API → Observation data service: returns observations
- Site data workflow → Site filters: filters sites
- Site data workflow → Site features: builds features
- Site data workflow → Observation averages: computes averages
- Map page → Map view: renders
- Map page → Map setup: initializes map
- Map page → Site layer: sets up layer
- Map page → Polygon layers: sets up layers
- Map page → Terrain layer: sets up layer
- Map page → DeckGL layer: sets up layer
- Map page → Twin raster: sets up raster
- Twin raster → Raster service: fetches TIFF
- Twin raster → TIFF parser: parses TIFF
- Map page → Indicators: renders
- Map page → Timeline: renders
- Map page → Site detail dialog: renders when selected
- Map page → Profiler analysis: renders profiler
- Profiler analysis → Profiler data service: loads profiler data
- Map page → GFS dialog: hosts dialog
- GFS dialog → Wind calculation: calculates wind
- Map page → Calculations UI: renders
- Map page → Site list page: links to list view
