# sp4chi/agencydesk architecture

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

- Interactive diagram: https://gitdiagram.com/sp4chi/agencydesk
- Repository: https://github.com/sp4chi/agencydesk

## Overview

AgencyDesk is a multi-agency project-management app with separate staff and client experiences. Users log in, choose an agency, and work within that membership; staff manage projects and tasks, while clients see shared work and can review files. The backend uses a tenant-scoped request context and database-enforced access rules, with routers, services, and repositories separating HTTP, business logic, and queries. README capabilities support the broad domain branches; sampled source and the SOURCE INDEX establish only the specific wiring shown below, so unverified subsystem links are omitted.

Main entry points: [`backend/app/main.py`](https://github.com/sp4chi/agencydesk/blob/main/backend/app/main.py) (FastAPI application), [`frontend/src/api/client.ts`](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/api/client.ts) (API client), [`frontend/src/App.tsx`](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/App.tsx) (Route application), [`frontend/src/auth/SessionProvider.tsx`](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/auth/SessionProvider.tsx) (Session state)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_identity["Identity and access"]
  node_session["Session state"]
  node_auth_routes["Authentication routes<br/>[auth.py]"]
  node_auth_service["Login and invite rules<br/>[service.py]"]
  node_auth_repo["Identity queries<br/>[repository.py]"]
end

subgraph group_frontend["Web experiences"]
  node_app_router["Route application<br/>[App.tsx]"]
  node_login["Login and agency selection<br/>[LoginPage.tsx]"]
  node_invite_accept["Invite acceptance"]
  node_staff_ui["Staff workspace"]
  node_portal_ui["Client portal"]
  node_portal_task["Portal task panel"]
  node_api_client["API client<br/>[client.ts]"]
end

subgraph group_api["API and domain"]
  node_api_entry["FastAPI application<br/>[main.py]"]
  node_project_routes["Project and client routes"]
  node_task_routes["Task routes<br/>[tasks.py]"]
  node_task_service["Task rules<br/>[tasks.py]"]
  node_collaboration["Comments and files"]
  node_time_team["Time and team"]
  node_dashboard_invites["Dashboard and invites"]
end

subgraph group_data["Tenant data and storage"]
  node_tenant_context["Tenant request context<br/>[db.py]"]
  node_task_repo["Task queries<br/>[tasks.py]"]
  node_file_storage["Uploaded file storage<br/>[storage.py]"]
  node_postgres[("PostgreSQL with RLS")]
end

node_staff_user(("Agency staff"))
node_client_user(("Agency client"))

node_staff_user -->|"signs in"| node_login
node_client_user -->|"signs in"| node_login
node_app_router -->|"provides session"| node_session
node_app_router -->|"routes staff"| node_staff_ui
node_app_router -->|"routes portal"| node_portal_ui
node_app_router -->|"routes invite"| node_invite_accept
node_login -->|"starts login"| node_session
node_session -->|"binds token"| node_api_client
node_session -->|"requests session"| node_auth_routes
node_invite_accept -->|"calls API"| node_api_client
node_staff_ui -->|"calls API"| node_api_client
node_portal_ui -->|"calls API"| node_api_client
node_portal_task -->|"loads task data"| node_api_client
node_api_client -->|"sends requests"| node_api_entry
node_api_entry -->|"registers routes"| node_auth_routes
node_api_entry -->|"registers routes"| node_project_routes
node_api_entry -->|"registers routes"| node_task_routes
node_api_entry -->|"registers routes"| node_time_team
node_api_entry -->|"registers routes"| node_dashboard_invites
node_api_entry -->|"configures storage"| node_collaboration
node_auth_routes -->|"invokes rules"| node_auth_service
node_auth_service -->|"queries memberships"| node_auth_repo
node_task_routes -->|"calls service"| node_task_service
node_task_service -->|"queries tasks"| node_task_repo
node_task_routes -->|"receives scoped DB"| node_tenant_context
node_tenant_context -->|"sets RLS context"| node_postgres
node_task_repo -->|"reads and writes"| node_postgres
node_file_storage -.->|"stores metadata separately"| node_postgres
node_client_user -->|"views shared work"| node_portal_ui
node_staff_user -->|"manages work"| node_staff_ui

click node_app_router "https://github.com/sp4chi/agencydesk/blob/main/frontend/src/App.tsx"
click node_session "https://github.com/sp4chi/agencydesk/blob/main/frontend/src/auth/SessionProvider.tsx"
click node_login "https://github.com/sp4chi/agencydesk/blob/main/frontend/src/shared/LoginPage.tsx"
click node_invite_accept "https://github.com/sp4chi/agencydesk/blob/main/frontend/src/shared/AcceptInvitePage.tsx"
click node_staff_ui "https://github.com/sp4chi/agencydesk/tree/main/frontend/src/staff"
click node_portal_ui "https://github.com/sp4chi/agencydesk/tree/main/frontend/src/portal"
click node_portal_task "https://github.com/sp4chi/agencydesk/blob/main/frontend/src/portal/PortalTaskPanel.tsx"
click node_api_client "https://github.com/sp4chi/agencydesk/blob/main/frontend/src/api/client.ts"
click node_api_entry "https://github.com/sp4chi/agencydesk/blob/main/backend/app/main.py"
click node_auth_routes "https://github.com/sp4chi/agencydesk/blob/main/backend/app/routers/auth.py"
click node_auth_service "https://github.com/sp4chi/agencydesk/blob/main/backend/app/auth/service.py"
click node_auth_repo "https://github.com/sp4chi/agencydesk/blob/main/backend/app/auth/repository.py"
click node_tenant_context "https://github.com/sp4chi/agencydesk/blob/main/backend/app/db.py"
click node_project_routes "https://github.com/sp4chi/agencydesk/tree/main/backend/app/routers"
click node_task_routes "https://github.com/sp4chi/agencydesk/blob/main/backend/app/routers/tasks.py"
click node_task_service "https://github.com/sp4chi/agencydesk/blob/main/backend/app/services/tasks.py"
click node_task_repo "https://github.com/sp4chi/agencydesk/blob/main/backend/app/repositories/tasks.py"
click node_collaboration "https://github.com/sp4chi/agencydesk/tree/main/backend/app/services"
click node_time_team "https://github.com/sp4chi/agencydesk/tree/main/backend/app/routers"
click node_dashboard_invites "https://github.com/sp4chi/agencydesk/tree/main/backend/app/routers"
click node_file_storage "https://github.com/sp4chi/agencydesk/blob/main/backend/app/services/storage.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_session,node_auth_routes,node_auth_service,node_auth_repo,node_client_user toneBlue
class node_app_router,node_login,node_invite_accept,node_staff_ui,node_portal_ui,node_portal_task,node_api_client toneAmber
class node_api_entry,node_project_routes,node_task_routes,node_task_service,node_collaboration,node_time_team,node_dashboard_invites toneMint
class node_tenant_context,node_task_repo,node_file_storage,node_postgres toneRose
class node_staff_user toneIndigo
```

## Components

### Identity and access

- [Session state](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/auth/SessionProvider.tsx): `frontend/src/auth/SessionProvider.tsx`
- [Authentication routes](https://github.com/sp4chi/agencydesk/blob/main/backend/app/routers/auth.py): `backend/app/routers/auth.py`
- [Login and invite rules](https://github.com/sp4chi/agencydesk/blob/main/backend/app/auth/service.py): `backend/app/auth/service.py`
- [Identity queries](https://github.com/sp4chi/agencydesk/blob/main/backend/app/auth/repository.py): `backend/app/auth/repository.py`

### Web experiences

- [Route application](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/App.tsx): `frontend/src/App.tsx`
- [Login and agency selection](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/shared/LoginPage.tsx): `frontend/src/shared/LoginPage.tsx`
- [Invite acceptance](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/shared/AcceptInvitePage.tsx): `frontend/src/shared/AcceptInvitePage.tsx`
- [Staff workspace](https://github.com/sp4chi/agencydesk/tree/main/frontend/src/staff): `frontend/src/staff`
- [Client portal](https://github.com/sp4chi/agencydesk/tree/main/frontend/src/portal): `frontend/src/portal`
- [Portal task panel](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/portal/PortalTaskPanel.tsx): `frontend/src/portal/PortalTaskPanel.tsx`
- [API client](https://github.com/sp4chi/agencydesk/blob/main/frontend/src/api/client.ts): `frontend/src/api/client.ts`

### API and domain

- [FastAPI application](https://github.com/sp4chi/agencydesk/blob/main/backend/app/main.py): `backend/app/main.py`
- [Project and client routes](https://github.com/sp4chi/agencydesk/tree/main/backend/app/routers): `backend/app/routers`
- [Task routes](https://github.com/sp4chi/agencydesk/blob/main/backend/app/routers/tasks.py): `backend/app/routers/tasks.py`
- [Task rules](https://github.com/sp4chi/agencydesk/blob/main/backend/app/services/tasks.py): `backend/app/services/tasks.py`
- [Comments and files](https://github.com/sp4chi/agencydesk/tree/main/backend/app/services): `backend/app/services`
- [Time and team](https://github.com/sp4chi/agencydesk/tree/main/backend/app/routers): `backend/app/routers`
- [Dashboard and invites](https://github.com/sp4chi/agencydesk/tree/main/backend/app/routers): `backend/app/routers`

### Tenant data and storage

- [Tenant request context](https://github.com/sp4chi/agencydesk/blob/main/backend/app/db.py): `backend/app/db.py`
- [Task queries](https://github.com/sp4chi/agencydesk/blob/main/backend/app/repositories/tasks.py): `backend/app/repositories/tasks.py`
- [Uploaded file storage](https://github.com/sp4chi/agencydesk/blob/main/backend/app/services/storage.py): `backend/app/services/storage.py`
- **PostgreSQL with RLS**

### Other components

- **Agency staff**
- **Agency client**

## Connections

- Agency staff → Login and agency selection: signs in
- Agency client → Login and agency selection: signs in
- Route application → Session state: provides session (evidence: `frontend/src/App.tsx`)
- Route application → Staff workspace: routes staff (evidence: `frontend/src/App.tsx`)
- Route application → Client portal: routes portal (evidence: `frontend/src/App.tsx`)
- Route application → Invite acceptance: routes invite (evidence: `frontend/src/App.tsx`)
- Login and agency selection → Session state: starts login (evidence: `frontend/src/shared/LoginPage.tsx`)
- Session state → API client: binds token (evidence: `frontend/src/auth/SessionProvider.tsx`)
- Session state → Authentication routes: requests session
- Invite acceptance → API client: calls API (evidence: `frontend/src/shared/AcceptInvitePage.tsx`)
- Staff workspace → API client: calls API (evidence: `frontend/src/staff/ProjectsPage.tsx`)
- Client portal → API client: calls API (evidence: `frontend/src/portal/PortalProjectPage.tsx`)
- Portal task panel → API client: loads task data (evidence: `frontend/src/portal/PortalTaskPanel.tsx`)
- API client → FastAPI application: sends requests
- FastAPI application → Authentication routes: registers routes (evidence: `backend/app/main.py`)
- FastAPI application → Project and client routes: registers routes (evidence: `backend/app/main.py`)
- FastAPI application → Task routes: registers routes (evidence: `backend/app/main.py`)
- FastAPI application → Time and team: registers routes (evidence: `backend/app/main.py`)
- FastAPI application → Dashboard and invites: registers routes (evidence: `backend/app/main.py`)
- FastAPI application → Comments and files: configures storage (evidence: `backend/app/main.py`)
- Authentication routes → Login and invite rules: invokes rules (evidence: `backend/app/routers/auth.py`)
- Login and invite rules → Identity queries: queries memberships (evidence: `backend/app/auth/service.py`)
- Task routes → Task rules: calls service (evidence: `backend/app/routers/tasks.py`)
- Task rules → Task queries: queries tasks (evidence: `backend/app/services/tasks.py`)
- Task routes → Tenant request context: receives scoped DB (evidence: `backend/app/routers/tasks.py`)
- Tenant request context → PostgreSQL with RLS: sets RLS context (evidence: `backend/app/db.py`)
- Task queries → PostgreSQL with RLS: reads and writes (evidence: `backend/app/repositories/tasks.py`)
- Uploaded file storage → PostgreSQL with RLS: stores metadata separately
- Agency client → Client portal: views shared work
- Agency staff → Staff workspace: manages work
