# 252627-bhif-syp/terranova architecture

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

- Interactive diagram: https://gitdiagram.com/252627-bhif-syp/terranova
- Repository: https://github.com/252627-bhif-syp/terranova

## Overview

1. **Overall shape**
   - TerraNova is a three-part monorepo: a **React/Vite frontend**, an **ASP.NET Core backend**, and a small **Node-based geospatial service**.  
   - The product goal, from the README, is an interactive climate-learning platform centered on a **3D globe**, country exploration, scenario sliders, and AI-assisted quizzes.

2. **Frontend as the main user-facing subsystem**
   - `terranova/frontend` is the presentation layer, built with **TypeScript + React** and bundled with **Vite**.
   - `App.tsx`, `main.tsx`, and the `components/` tree show a componentized UI split into areas like:
     - globe visualization (`GlobeScene`)
     - country info overlays/popups (`CountryPopup`, `LanguageFamilyPopup`)
     - climate narrative panels (`ClimateInsightPanel`)
     - authentication/account UI (`AuthModal`, `AccountPage`, `UserMenu`)
     - quiz UX (`Quiz/*`)
   - State is shared through React contexts such as `AuthContext` and `GlobeContext`, which are the main client-side coordination points.

3. **Client-side data-heavy visualization**
   - A large portion of the climate and geography content is shipped as **static files** under `frontend/public/data` and `frontend/src/data`.
   - This includes GeoJSON, JSON timelines, scenario datasets, species/red-list tables, and historical climate series.  
   - Architecturally, this means many visualizations are likely **data-driven in the browser**, with the frontend reading preprocessed assets rather than requesting every chart or map layer from the backend.

4. **Data preprocessing and content pipeline**
   - The frontend contains scripts under `frontend/scripts/` for transforming climate and biodiversity datasets before they are served.
   - There is also a root `fetch_languages.mjs`, suggesting some content is generated or refreshed outside the app runtime.
   - This creates a clear boundary between **offline/prebuild data preparation** and **runtime UI rendering**.

5. **Backend API layer**
   - `terranova/backend/TerraNova.Api` is an **ASP.NET Core Minimal API** app exposing the server-side entry points.
   - The endpoint groups are explicitly separated by domain:
     - `AuthEndpoints`
     - `ChatEndpoints`
     - `CountriesEndpoints`
     - `QuizEndpoints`
     - `TeamEndpoints`
     - `UnsplashEndpoints`
   - This suggests the backend is the orchestration layer for identity, AI/chat, country metadata, quiz persistence, team/community features, and external image lookup.

6. **Core domain boundary**
   - `TerraNova.Core` holds the shared domain contracts:
     - models like `Country`, `Quiz`, `Question`, `QuizResult`, `User`, `ChatRequest`, `ChatResponse`
     - service interfaces like `IChatService` and `IJwtService`
   - This is the architecture boundary that keeps business concepts independent from web, database, or third-party implementation details.

7. **Infrastructure and persistence**
   - `TerraNova.Infrastructure` contains the concrete integrations:
     - `ApplicationDbContext` for **Entity Framework Core**
     - `DbSeeder` for initial data
     - EF migrations for evolving the schema
     - service implementations like `JwtService`, `GeminiChatService`, and `UnsplashService`
   - The migration history indicates the backend persists structured application data such as users, quizzes, and quiz results in a relational database, likely PostgreSQL given the K8s manifest naming.

8. **External service integrations**
   - The backend is the integration point for external APIs:
     - **Gemini** via `GeminiChatService` for AI-driven chat or quiz generation
     - **Unsplash** via `UnsplashService` for image content
     - **JWT** for authentication tokens
   - These integrations are isolated behind interfaces, so the API layer depends on stable contracts rather than vendor-specific code.

9. **Geospatial auxiliary service**
   - `terranova/gee-service` is a separate **Node.js service** with its own Dockerfile and `server.js`.
   - Given the name and the repository’s globe/climate focus, it likely acts as a specialized service for geospatial/earth-engine-style processing or map-related requests.
   - Its separate deployment indicates it is treated as an independent runtime boundary, not just a library.

10. **Deployment and runtime topology**
   - The repo includes both `docker-compose.yml` and Kubernetes manifests under `k8s/`.
   - Kubernetes resources are split by subsystem: `frontend`, `backend`, `gee-service`, plus backend PostgreSQL and ingress.
   - This means the production architecture is containerized and routed through an ingress, with each service deployed independently.

11. **How requests flow through the system**
   - The browser loads the React frontend, which reads static climate/geography datasets locally for fast visualization.
   - When the user authenticates, asks AI questions, saves quiz progress, or fetches country/team data, the frontend calls the ASP.NET API.
   - The API then:
     - validates/authenticates with JWT
     - reads/writes application data through EF Core
     - forwards AI/image requests to Gemini or Unsplash
     - optionally coordinates with the geospatial service for specialized map data

12. **Supporting assets and project documentation**
   - The `Docs/` folder contains personas, research, user stories, testing feedback, and vector DB research, which shows the repo is both a product implementation and an evolving project definition.
   - The `.agents/skills` directory is developer tooling/documentation for consistent implementation patterns, but it does not change runtime architecture.

Main entry points: [`terranova/frontend/src/App.tsx`](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/App.tsx) (App shell), [`terranova/backend/TerraNova.Api/Program.cs`](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Api/Program.cs) (API host), [`terranova/frontend/public/data/climate_zones.json`](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/public/data/climate_zones.json) (Static data), [`terranova/docker-compose.yml`](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/docker-compose.yml) (Compose)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Frontend"]
  node_frontend_app["App shell<br/>React entry<br/>[App.tsx]"]
  node_frontend_main["Main entry<br/>Vite bootstrap<br/>[main.tsx]"]
  node_frontend_globe(("Globe scene<br/>3D visualization<br/>[GlobeScene.tsx]"))
  node_frontend_panels["Info panels<br/>UI overlays<br/>[CountryPopup.tsx]"]
  node_frontend_auth["Auth UI<br/>client auth<br/>[AuthModal.tsx]"]
  node_frontend_quiz["Quiz UI<br/>learning flow<br/>[QuizDashboard.tsx]"]
  node_frontend_contexts{{"Client state<br/>React context<br/>[GlobeContext.tsx]"}}
  node_frontend_data[("Static data<br/>browser datasets<br/>[climate_zones.json]")]
  node_frontend_scripts["Data scripts<br/>prebuild pipeline"]
end

subgraph group_backend["Backend"]
  node_backend_api["API host<br/>Minimal API<br/>[Program.cs]"]
  node_backend_endpoints["Endpoint groups<br/>HTTP routes<br/>[AuthEndpoints.cs]"]
  node_core_domain{{"Core models<br/>domain contracts<br/>[Country.cs]"}}
  node_infra_data[("Persistence<br/>EF Core")]
  node_infra_services["Integrations<br/>external services"]
end

subgraph group_services["Services"]
  node_gee_service["GEE service<br/>Node service<br/>[server.js]"]
end

subgraph group_deploy["Deployment"]
  node_docker_compose["Compose<br/>local orchestration<br/>[docker-compose.yml]"]
  node_k8s_backend["Backend deploy<br/>Kubernetes manifests<br/>[deployment.yaml]"]
  node_k8s_frontend["Frontend deploy<br/>Kubernetes manifests<br/>[deployment.yaml]"]
  node_k8s_gee["GEE deploy<br/>Kubernetes manifests<br/>[deployment.yaml]"]
  node_k8s_ingress["Ingress<br/>cluster routing<br/>[ingress.yaml]"]
end

node_frontend_main -->|"boots"| node_frontend_app
node_frontend_app -->|"hosts"| node_frontend_globe
node_frontend_app -->|"shows"| node_frontend_panels
node_frontend_app -->|"shows"| node_frontend_auth
node_frontend_app -->|"shows"| node_frontend_quiz
node_frontend_app -->|"shares state"| node_frontend_contexts
node_frontend_globe -->|"reads"| node_frontend_data
node_frontend_panels -->|"reads"| node_frontend_data
node_frontend_quiz -->|"reads"| node_frontend_data
node_frontend_scripts -.->|"builds"| node_frontend_data
node_frontend_app -->|"calls"| node_backend_api
node_backend_api -->|"exposes"| node_backend_endpoints
node_backend_endpoints -->|"uses"| node_core_domain
node_backend_api -->|"depends on"| node_infra_services
node_backend_api -->|"persists via"| node_infra_data
node_infra_services -->|"implements"| node_core_domain
node_infra_data -->|"stores"| node_core_domain
node_backend_api -.->|"coordinates"| node_gee_service
node_docker_compose -->|"runs"| node_frontend_app
node_docker_compose -->|"runs"| node_backend_api
node_docker_compose -->|"runs"| node_gee_service
node_k8s_ingress -->|"routes to"| node_k8s_frontend
node_k8s_ingress -->|"routes to"| node_k8s_backend
node_k8s_ingress -->|"routes to"| node_k8s_gee
node_k8s_backend -->|"deploys"| node_backend_api
node_k8s_frontend -->|"deploys"| node_frontend_app
node_k8s_gee -->|"deploys"| node_gee_service

click node_frontend_app "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/App.tsx"
click node_frontend_main "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/main.tsx"
click node_frontend_globe "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/components/GlobeScene/GlobeScene.tsx"
click node_frontend_panels "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/components/CountryPopup/CountryPopup.tsx"
click node_frontend_auth "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/components/AuthModal/AuthModal.tsx"
click node_frontend_quiz "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/components/Quiz/QuizDashboard.tsx"
click node_frontend_contexts "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/contexts/GlobeContext.tsx"
click node_frontend_data "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/public/data/climate_zones.json"
click node_frontend_scripts "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/scripts/process_co2_data.cjs"
click node_backend_api "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Api/Program.cs"
click node_backend_endpoints "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Api/Endpoints/AuthEndpoints.cs"
click node_core_domain "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Core/Models/Country.cs"
click node_infra_data "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Infrastructure/Data/ApplicationDbContext.cs"
click node_infra_services "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Infrastructure/Services/GeminiChatService.cs"
click node_gee_service "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/gee-service/server.js"
click node_docker_compose "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/docker-compose.yml"
click node_k8s_backend "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/k8s/backend/deployment.yaml"
click node_k8s_frontend "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/k8s/frontend/deployment.yaml"
click node_k8s_gee "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/k8s/gee-service/deployment.yaml"
click node_k8s_ingress "https://github.com/252627-bhif-syp/terranova/blob/main/terranova/k8s/ingress.yaml"

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_app,node_frontend_main,node_frontend_globe,node_frontend_panels,node_frontend_auth,node_frontend_quiz,node_frontend_contexts,node_frontend_data,node_frontend_scripts toneBlue
class node_backend_api,node_backend_endpoints,node_core_domain,node_infra_data,node_infra_services toneAmber
class node_gee_service toneMint
class node_docker_compose,node_k8s_backend,node_k8s_frontend,node_k8s_gee,node_k8s_ingress toneRose
```

## Components

### Frontend

React/Vite client and its browser-side data and UI layers

- [App shell](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/App.tsx): React entry · Top-level client composition and bootstrapping · `terranova/frontend/src/App.tsx`
- [Main entry](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/main.tsx): Vite bootstrap · Client startup and React rendering · `terranova/frontend/src/main.tsx`
- [Globe scene](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/components/GlobeScene/GlobeScene.tsx): 3D visualization · Primary interactive globe and map interaction surface · `terranova/frontend/src/components/GlobeScene/GlobeScene.tsx`
- [Info panels](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/components/CountryPopup/CountryPopup.tsx): UI overlays · Country, climate, and language popups and insights · `terranova/frontend/src/components/CountryPopup/CountryPopup.tsx`
- [Auth UI](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/components/AuthModal/AuthModal.tsx): client auth · Login, account, and user menu flows · `terranova/frontend/src/components/AuthModal/AuthModal.tsx`
- [Quiz UI](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/components/Quiz/QuizDashboard.tsx): learning flow · Quiz creation, play, and dashboard experience · `terranova/frontend/src/components/Quiz/QuizDashboard.tsx`
- [Client state](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/src/contexts/GlobeContext.tsx): React context · Shared globe and authentication state · `terranova/frontend/src/contexts/GlobeContext.tsx`
- [Static data](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/public/data/climate_zones.json): browser datasets · Preloaded climate, geography, and biodiversity assets · `terranova/frontend/public/data/climate_zones.json`
- [Data scripts](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/frontend/scripts/process_co2_data.cjs): prebuild pipeline · Offline transforms for climate and biodiversity content · `terranova/frontend/scripts/process_co2_data.cjs`

### Backend

ASP.NET Core API, core domain, and infrastructure

- [API host](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Api/Program.cs): Minimal API · ASP.NET Core server and endpoint composition · `terranova/backend/TerraNova.Api/Program.cs`
- [Endpoint groups](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Api/Endpoints/AuthEndpoints.cs): HTTP routes · Domain-routed API surface for auth, chat, countries, quiz, team, and images · `terranova/backend/TerraNova.Api/Endpoints/AuthEndpoints.cs`
- [Core models](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Core/Models/Country.cs): domain contracts · Shared entities, requests, and service interfaces · `terranova/backend/TerraNova.Core/Models/Country.cs`
- [Persistence](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Infrastructure/Data/ApplicationDbContext.cs): EF Core · DbContext, seeding, migrations, and relational schema evolution · `terranova/backend/TerraNova.Infrastructure/Data/ApplicationDbContext.cs`
- [Integrations](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/backend/TerraNova.Infrastructure/Services/GeminiChatService.cs): external services · JWT, Gemini chat, and Unsplash adapters · `terranova/backend/TerraNova.Infrastructure/Services/GeminiChatService.cs`

### Services

Standalone auxiliary runtime

- [GEE service](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/gee-service/server.js): Node service · Separate geospatial runtime for specialized map processing · `terranova/gee-service/server.js`

### Deployment

Container and cluster manifests

- [Compose](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/docker-compose.yml): local orchestration · Multi-service local runtime wiring · `terranova/docker-compose.yml`
- [Backend deploy](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/k8s/backend/deployment.yaml): Kubernetes manifests · Backend, database, and service resources · `terranova/k8s/backend/deployment.yaml`
- [Frontend deploy](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/k8s/frontend/deployment.yaml): Kubernetes manifests · Frontend service and deployment resources · `terranova/k8s/frontend/deployment.yaml`
- [GEE deploy](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/k8s/gee-service/deployment.yaml): Kubernetes manifests · Standalone deployment for the geospatial service · `terranova/k8s/gee-service/deployment.yaml`
- [Ingress](https://github.com/252627-bhif-syp/terranova/blob/main/terranova/k8s/ingress.yaml): cluster routing · External traffic entrypoint and routing · `terranova/k8s/ingress.yaml`

## Connections

- Main entry → App shell: boots · Entry point renders the app shell
- App shell → Globe scene: hosts · App embeds the interactive globe scene
- App shell → Info panels: shows · App coordinates overlay content
- App shell → Auth UI: shows · App opens authentication and account flows
- App shell → Quiz UI: shows · App routes into quiz experience
- App shell → Client state: shares state · UI composition depends on client-side contexts
- Globe scene → Static data: reads · Visualization is driven by static geo and climate assets
- Info panels → Static data: reads · Popups and insights consume bundled datasets
- Quiz UI → Static data: reads · Quiz UI consumes preprocessed content where available
- Data scripts → Static data: builds · Offline scripts generate or normalize served datasets
- App shell → API host: calls · Client requests server-side features and persisted data
- API host → Endpoint groups: exposes · Program wires domain endpoint groups
- Endpoint groups → Core models: uses · Routes operate on shared domain contracts
- API host → Integrations: depends on · API delegates external integrations to infrastructure services
- API host → Persistence: persists via · API reads and writes through EF-backed persistence
- Integrations → Core models: implements · Infrastructure fulfills shared service interfaces
- Persistence → Core models: stores · Database persists domain entities
- API host → GEE service: coordinates · API can delegate specialized geospatial work
- Compose → App shell: runs · Local composition includes the frontend runtime
- Compose → API host: runs · Local composition includes the backend runtime
- Compose → GEE service: runs · Local composition includes the geospatial service
- Ingress → Frontend deploy: routes to · Ingress sends browser traffic to the frontend service
- Ingress → Backend deploy: routes to · Ingress sends API traffic to the backend service
- Ingress → GEE deploy: routes to · Ingress can expose the geospatial service
- Backend deploy → API host: deploys · Kubernetes backend manifests package the API and database
- Frontend deploy → App shell: deploys · Kubernetes frontend manifests package the client
- GEE deploy → GEE service: deploys · Kubernetes manifests package the Node geospatial service
