# maelbel/skillspector-web architecture

> Architecture diagram of the GitHub repository maelbel/skillspector-web, 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/maelbel/skillspector-web
- Repository: https://github.com/maelbel/skillspector-web

## Overview

Skillspector Web lets visitors submit an HTTP(S) skill URL, track an asynchronous scan, and review its risk score and findings. The Nuxt UI sends same-origin requests through Nitro proxy routes to a FastAPI service; the service runs the skillspector analysis pipeline and persists scan history in SQLite. The product also exposes scan logs, history management, settings, and token-gated administration, including Claude CLI login and retention controls. The README documents these capabilities, but backend route and scanner source excerpts were not supplied, so uncertain internal wiring is omitted.

Main entry points: [`backend/app/api/routes/scan.py`](https://github.com/maelbel/skillspector-web/blob/main/backend/app/api/routes/scan.py) (Scan endpoints), [`app/pages/admin.vue`](https://github.com/maelbel/skillspector-web/blob/main/app/pages/admin.vue) (Admin page), [`backend/app/main.py`](https://github.com/maelbel/skillspector-web/blob/main/backend/app/main.py) (FastAPI application), [`backend/app/api/routes/admin.py`](https://github.com/maelbel/skillspector-web/blob/main/backend/app/api/routes/admin.py) (Admin endpoints)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_experience["Web experience"]
  node_home["Scan home<br/>[index.vue]"]
  node_scan_form["Scan form<br/>[ScanForm.vue]"]
  node_result_page["Scan result<br/>[&#91;id&#93;.vue]"]
  node_scan_status["Status polling<br/>[useScanStatus.ts]"]
  node_scan_logs["Log polling<br/>[useScanLogs.ts]"]
  node_history_page["History page<br/>[history.vue]"]
  node_admin_page["Admin page<br/>[admin.vue]"]
end

subgraph group_proxy["Nitro API proxy"]
  node_scan_proxy["Scan proxy<br/>[scan.post.ts]"]
  node_status_proxy["Status proxy<br/>[&#91;id&#93;.get.ts]"]
  node_logs_proxy["Logs proxy<br/>[logs.get.ts]"]
  node_history_proxy["History proxy<br/>[index.get.ts]"]
  node_delete_proxy["Delete proxy<br/>[index.delete.ts]"]
  node_settings_proxy["Settings proxy<br/>[settings.get.ts]"]
  node_settings_write_proxy["Settings update proxy<br/>[settings.put.ts]"]
  node_claude_start_proxy["Claude login start<br/>[start.post.ts]"]
  node_claude_complete_proxy["Claude login complete<br/>[complete.post.ts]"]
end

subgraph group_service["Scan service"]
  node_fastapi["FastAPI application<br/>[main.py]"]
  node_scan_routes["Scan endpoints<br/>[scan.py]"]
  node_scanner["Skillspector runner<br/>[scanner.py]"]
  node_scan_db[("Scan history store<br/>[db.py]")]
  node_logs_backend["Scan log service<br/>[scan_logs.py]"]
end

subgraph group_admin["History and admin"]
  node_admin_routes["Admin endpoints<br/>[admin.py]"]
  node_settings_routes["Settings endpoints<br/>[settings.py]"]
  node_retention["Retention service<br/>[retention.py]"]
end

node_visitor(("Visitor"))
node_skillspector{{"skillspector pipeline"}}
node_llm_provider(("AI provider"))
node_claude_cli(("Claude CLI session"))

node_visitor -->|"opens"| node_home
node_home -->|"presents"| node_scan_form
node_scan_form -->|"submits scan"| node_scan_proxy
node_scan_proxy -->|"forwards request"| node_scan_routes
node_scan_routes -->|"starts scan"| node_scanner
node_scanner -->|"invokes pipeline"| node_skillspector
node_scan_status -->|"polls status"| node_status_proxy
node_status_proxy -->|"forwards request"| node_scan_routes
node_result_page -->|"tracks scan"| node_scan_status
node_result_page -->|"shows logs"| node_scan_logs
node_scan_logs -->|"polls logs"| node_logs_proxy
node_logs_proxy -->|"forwards request"| node_scan_routes
node_scan_routes -->|"reads and writes"| node_scan_db
node_scan_routes -->|"records logs"| node_logs_backend
node_visitor -->|"opens"| node_history_page
node_history_page -->|"loads scans"| node_history_proxy
node_history_page -->|"deletes scan"| node_delete_proxy
node_history_proxy -->|"forwards request"| node_scan_routes
node_delete_proxy -->|"forwards request"| node_scan_routes
node_visitor -->|"opens"| node_admin_page
node_admin_page -->|"loads settings"| node_settings_proxy
node_admin_page -->|"updates settings"| node_settings_write_proxy
node_admin_page -->|"starts login"| node_claude_start_proxy
node_admin_page -->|"completes login"| node_claude_complete_proxy
node_settings_proxy -->|"forwards request"| node_settings_routes
node_settings_write_proxy -->|"forwards request"| node_settings_routes
node_claude_start_proxy -->|"forwards request"| node_admin_routes
node_claude_complete_proxy -->|"forwards request"| node_admin_routes
node_fastapi -->|"registers routes"| node_scan_routes
node_fastapi -->|"registers routes"| node_admin_routes
node_fastapi -->|"registers routes"| node_settings_routes
node_fastapi -->|"starts service"| node_retention
node_scanner -.->|"uses optionally"| node_llm_provider
node_admin_routes -.->|"checks login"| node_claude_cli

click node_home "https://github.com/maelbel/skillspector-web/blob/main/app/pages/index.vue"
click node_scan_form "https://github.com/maelbel/skillspector-web/blob/main/app/components/ScanForm.vue"
click node_result_page "https://github.com/maelbel/skillspector-web/blob/main/app/pages/scan/%5Bid%5D.vue"
click node_scan_status "https://github.com/maelbel/skillspector-web/blob/main/app/composables/useScanStatus.ts"
click node_scan_logs "https://github.com/maelbel/skillspector-web/blob/main/app/composables/useScanLogs.ts"
click node_history_page "https://github.com/maelbel/skillspector-web/blob/main/app/pages/history.vue"
click node_admin_page "https://github.com/maelbel/skillspector-web/blob/main/app/pages/admin.vue"
click node_scan_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/scan.post.ts"
click node_status_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/scan/%5Bid%5D.get.ts"
click node_logs_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/scan/%5Bid%5D/logs.get.ts"
click node_history_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/scan/index.get.ts"
click node_delete_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/scan/%5Bid%5D/index.delete.ts"
click node_settings_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/settings.get.ts"
click node_settings_write_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/settings.put.ts"
click node_claude_start_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/admin/claude-login/start.post.ts"
click node_claude_complete_proxy "https://github.com/maelbel/skillspector-web/blob/main/server/api/admin/claude-login/complete.post.ts"
click node_fastapi "https://github.com/maelbel/skillspector-web/blob/main/backend/app/main.py"
click node_scan_routes "https://github.com/maelbel/skillspector-web/blob/main/backend/app/api/routes/scan.py"
click node_scanner "https://github.com/maelbel/skillspector-web/blob/main/backend/app/scanner.py"
click node_scan_db "https://github.com/maelbel/skillspector-web/blob/main/backend/app/db.py"
click node_logs_backend "https://github.com/maelbel/skillspector-web/blob/main/backend/app/scan_logs.py"
click node_admin_routes "https://github.com/maelbel/skillspector-web/blob/main/backend/app/api/routes/admin.py"
click node_settings_routes "https://github.com/maelbel/skillspector-web/blob/main/backend/app/api/routes/settings.py"
click node_retention "https://github.com/maelbel/skillspector-web/blob/main/backend/app/retention.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_home,node_scan_form,node_result_page,node_scan_status,node_scan_logs,node_history_page,node_admin_page toneBlue
class node_scan_proxy,node_status_proxy,node_logs_proxy,node_history_proxy,node_delete_proxy,node_settings_proxy,node_settings_write_proxy,node_claude_start_proxy,node_claude_complete_proxy toneAmber
class node_fastapi,node_scan_routes,node_scanner,node_scan_db,node_logs_backend toneMint
class node_admin_routes,node_settings_routes,node_retention toneRose
class node_visitor,node_skillspector,node_llm_provider,node_claude_cli toneIndigo
```

## Components

### Web experience

- [Scan home](https://github.com/maelbel/skillspector-web/blob/main/app/pages/index.vue): `app/pages/index.vue`
- [Scan form](https://github.com/maelbel/skillspector-web/blob/main/app/components/ScanForm.vue): `app/components/ScanForm.vue`
- [Scan result](https://github.com/maelbel/skillspector-web/blob/main/app/pages/scan/%5Bid%5D.vue): `app/pages/scan/[id].vue`
- [Status polling](https://github.com/maelbel/skillspector-web/blob/main/app/composables/useScanStatus.ts): `app/composables/useScanStatus.ts`
- [Log polling](https://github.com/maelbel/skillspector-web/blob/main/app/composables/useScanLogs.ts): `app/composables/useScanLogs.ts`
- [History page](https://github.com/maelbel/skillspector-web/blob/main/app/pages/history.vue): `app/pages/history.vue`
- [Admin page](https://github.com/maelbel/skillspector-web/blob/main/app/pages/admin.vue): `app/pages/admin.vue`

### Nitro API proxy

- [Scan proxy](https://github.com/maelbel/skillspector-web/blob/main/server/api/scan.post.ts): `server/api/scan.post.ts`
- [Status proxy](https://github.com/maelbel/skillspector-web/blob/main/server/api/scan/%5Bid%5D.get.ts): `server/api/scan/[id].get.ts`
- [Logs proxy](https://github.com/maelbel/skillspector-web/blob/main/server/api/scan/%5Bid%5D/logs.get.ts): `server/api/scan/[id]/logs.get.ts`
- [History proxy](https://github.com/maelbel/skillspector-web/blob/main/server/api/scan/index.get.ts): `server/api/scan/index.get.ts`
- [Delete proxy](https://github.com/maelbel/skillspector-web/blob/main/server/api/scan/%5Bid%5D/index.delete.ts): `server/api/scan/[id]/index.delete.ts`
- [Settings proxy](https://github.com/maelbel/skillspector-web/blob/main/server/api/settings.get.ts): `server/api/settings.get.ts`
- [Settings update proxy](https://github.com/maelbel/skillspector-web/blob/main/server/api/settings.put.ts): `server/api/settings.put.ts`
- [Claude login start](https://github.com/maelbel/skillspector-web/blob/main/server/api/admin/claude-login/start.post.ts): `server/api/admin/claude-login/start.post.ts`
- [Claude login complete](https://github.com/maelbel/skillspector-web/blob/main/server/api/admin/claude-login/complete.post.ts): `server/api/admin/claude-login/complete.post.ts`

### Scan service

- [FastAPI application](https://github.com/maelbel/skillspector-web/blob/main/backend/app/main.py): `backend/app/main.py`
- [Scan endpoints](https://github.com/maelbel/skillspector-web/blob/main/backend/app/api/routes/scan.py): `backend/app/api/routes/scan.py`
- [Skillspector runner](https://github.com/maelbel/skillspector-web/blob/main/backend/app/scanner.py): `backend/app/scanner.py`
- [Scan history store](https://github.com/maelbel/skillspector-web/blob/main/backend/app/db.py): `backend/app/db.py`
- [Scan log service](https://github.com/maelbel/skillspector-web/blob/main/backend/app/scan_logs.py): `backend/app/scan_logs.py`

### History and admin

- [Admin endpoints](https://github.com/maelbel/skillspector-web/blob/main/backend/app/api/routes/admin.py): `backend/app/api/routes/admin.py`
- [Settings endpoints](https://github.com/maelbel/skillspector-web/blob/main/backend/app/api/routes/settings.py): `backend/app/api/routes/settings.py`
- [Retention service](https://github.com/maelbel/skillspector-web/blob/main/backend/app/retention.py): `backend/app/retention.py`

### Other components

- **Visitor**
- **skillspector pipeline**
- **AI provider**
- **Claude CLI session**

## Connections

- Visitor → Scan home: opens
- Scan home → Scan form: presents
- Scan form → Scan proxy: submits scan
- Scan proxy → Scan endpoints: forwards request
- Scan endpoints → Skillspector runner: starts scan
- Skillspector runner → skillspector pipeline: invokes pipeline
- Status polling → Status proxy: polls status
- Status proxy → Scan endpoints: forwards request
- Scan result → Status polling: tracks scan
- Scan result → Log polling: shows logs
- Log polling → Logs proxy: polls logs
- Logs proxy → Scan endpoints: forwards request
- Scan endpoints → Scan history store: reads and writes
- Scan endpoints → Scan log service: records logs
- Visitor → History page: opens
- History page → History proxy: loads scans
- History page → Delete proxy: deletes scan
- History proxy → Scan endpoints: forwards request
- Delete proxy → Scan endpoints: forwards request
- Visitor → Admin page: opens
- Admin page → Settings proxy: loads settings
- Admin page → Settings update proxy: updates settings
- Admin page → Claude login start: starts login
- Admin page → Claude login complete: completes login
- Settings proxy → Settings endpoints: forwards request
- Settings update proxy → Settings endpoints: forwards request
- Claude login start → Admin endpoints: forwards request
- Claude login complete → Admin endpoints: forwards request
- FastAPI application → Scan endpoints: registers routes
- FastAPI application → Admin endpoints: registers routes
- FastAPI application → Settings endpoints: registers routes
- FastAPI application → Retention service: starts service
- Skillspector runner → AI provider: uses optionally
- Admin endpoints → Claude CLI session: checks login
