# chuyuchen80-byte/info-harbor architecture

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

- Interactive diagram: https://gitdiagram.com/chuyuchen80-byte/info-harbor
- Repository: https://github.com/chuyuchen80-byte/info-harbor

## Overview

info-harbor is a modular AI-news aggregation product intended to collect global sources, screen and assess items, then present them by country or region. The repository shows a Vue interface and a FastAPI backend, but much of the backend is still skeletal: the mounted article endpoints return placeholders, and the worker pipeline only publishes an event. The graph preserves documented product areas without implying that unsampled services are wired together; paths for broader domain areas use their existing directories.

Main entry points: [`frontend/src/App.vue`](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/App.vue) (Vue application), [`backend/app/main.py`](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/main.py) (FastAPI app), [`backend/app/worker.py`](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/worker.py) (Pipeline worker), [`backend/app/plugins/registry.py`](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/plugins/registry.py) (Source adapters)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["User interface"]
  node_vue_app["Vue application<br/>[App.vue]"]
  node_router["Page router<br/>[index.ts]"]
  node_article_views["Article views"]
  node_country_view["Country view<br/>[CountryView.vue]"]
  node_dashboard_view["Dashboard<br/>[DashboardView.vue]"]
  node_search_view["Search view<br/>[SearchView.vue]"]
  node_source_view["Source view<br/>[SourceView.vue]"]
  node_admin_view["Admin view<br/>[AdminView.vue]"]
  node_http_client["HTTP client<br/>[http.ts]"]
end

subgraph group_backend["Backend API"]
  node_api_app["FastAPI app<br/>[main.py]"]
  node_article_api["Article API<br/>[router.py]"]
  node_article_domain["Article domain"]
  node_sources_domain["Source domain"]
  node_screening_domain["Screening domain"]
  node_stats_domain["Statistics domain"]
  node_users_domain["User domain"]
  node_tasks_domain["Task domain"]
end

subgraph group_pipeline["Ingestion and assessment"]
  node_worker["Pipeline worker<br/>[worker.py]"]
  node_source_plugins["Source adapters<br/>[registry.py]"]
  node_llm_gateway["LLM gateway<br/>[llm_gateway.py]"]
end

subgraph group_shared["Shared infrastructure"]
  node_event_bus["Event bus<br/>[events.py]"]
  node_article_contract["Article contract<br/>[article.py]"]
end

node_reader(("Reader"))

node_reader -->|"opens"| node_vue_app
node_vue_app -->|"renders routes"| node_router
node_api_app -->|"mounts"| node_article_api
node_worker -->|"publishes event"| node_event_bus
node_source_plugins -.->|"normalizes to"| node_article_contract
node_llm_gateway -.->|"planned assessment"| node_screening_domain

click node_vue_app "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/App.vue"
click node_router "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/router/index.ts"
click node_article_views "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/ArticleListView.vue"
click node_country_view "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/CountryView.vue"
click node_dashboard_view "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/DashboardView.vue"
click node_search_view "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/SearchView.vue"
click node_source_view "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/SourceView.vue"
click node_admin_view "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/admin/AdminView.vue"
click node_http_client "https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/services/http.ts"
click node_api_app "https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/main.py"
click node_article_api "https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/domain/articles/api/router.py"
click node_article_domain "https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/articles"
click node_sources_domain "https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/sources"
click node_screening_domain "https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/screening"
click node_stats_domain "https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/stats"
click node_users_domain "https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/users"
click node_tasks_domain "https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/tasks"
click node_worker "https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/worker.py"
click node_source_plugins "https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/plugins/registry.py"
click node_llm_gateway "https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/core/llm_gateway.py"
click node_event_bus "https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/core/events.py"
click node_article_contract "https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/core/models/article.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_vue_app,node_router,node_article_views,node_country_view,node_dashboard_view,node_search_view,node_source_view,node_admin_view,node_http_client toneBlue
class node_api_app,node_article_api,node_article_domain,node_sources_domain,node_screening_domain,node_stats_domain,node_users_domain,node_tasks_domain toneAmber
class node_worker,node_source_plugins,node_llm_gateway toneMint
class node_event_bus,node_article_contract toneRose
class node_reader toneIndigo
```

## Components

### User interface

- [Vue application](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/App.vue): `frontend/src/App.vue`
- [Page router](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/router/index.ts): `frontend/src/router/index.ts`
- [Article views](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/ArticleListView.vue): `frontend/src/views/ArticleListView.vue`
- [Country view](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/CountryView.vue): `frontend/src/views/CountryView.vue`
- [Dashboard](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/DashboardView.vue): `frontend/src/views/DashboardView.vue`
- [Search view](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/SearchView.vue): `frontend/src/views/SearchView.vue`
- [Source view](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/SourceView.vue): `frontend/src/views/SourceView.vue`
- [Admin view](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/views/admin/AdminView.vue): `frontend/src/views/admin/AdminView.vue`
- [HTTP client](https://github.com/chuyuchen80-byte/info-harbor/blob/main/frontend/src/services/http.ts): `frontend/src/services/http.ts`

### Backend API

- [FastAPI app](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/main.py): `backend/app/main.py`
- [Article API](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/domain/articles/api/router.py): `backend/app/domain/articles/api/router.py`
- [Article domain](https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/articles): `backend/app/domain/articles`
- [Source domain](https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/sources): `backend/app/domain/sources`
- [Screening domain](https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/screening): `backend/app/domain/screening`
- [Statistics domain](https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/stats): `backend/app/domain/stats`
- [User domain](https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/users): `backend/app/domain/users`
- [Task domain](https://github.com/chuyuchen80-byte/info-harbor/tree/main/backend/app/domain/tasks): `backend/app/domain/tasks`

### Ingestion and assessment

- [Pipeline worker](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/worker.py): `backend/app/worker.py`
- [Source adapters](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/plugins/registry.py): `backend/app/plugins/registry.py`
- [LLM gateway](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/core/llm_gateway.py): `backend/app/core/llm_gateway.py`

### Shared infrastructure

- [Event bus](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/core/events.py): `backend/app/core/events.py`
- [Article contract](https://github.com/chuyuchen80-byte/info-harbor/blob/main/backend/app/core/models/article.py): `backend/app/core/models/article.py`

### Other components

- **Reader**

## Connections

- Reader → Vue application: opens
- Vue application → Page router: renders routes
- FastAPI app → Article API: mounts
- Pipeline worker → Event bus: publishes event
- Source adapters → Article contract: normalizes to
- LLM gateway → Screening domain: planned assessment
