# fcherchyk/kambi architecture

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

- Interactive diagram: https://gitdiagram.com/fcherchyk/kambi
- Repository: https://github.com/fcherchyk/kambi

## Overview

Kambi is a local, single-user kanban app. A user signs in, manages boards and their columns and card types, then creates, edits, orders, moves, archives, and restores cards and columns through the SPA and FastAPI API. The API enforces session ownership and version checks while persisting domain state in PostgreSQL. The diagram preserves the documented archive, keyboard, and optimistic-update UI capabilities; source excerpts are incomplete, so some documented links use the README as evidence.

Main entry points: [`api/app/db.py`](https://github.com/fcherchyk/kambi/blob/main/api/app/db.py) (Database sessions), [`api/app/boards/service.py`](https://github.com/fcherchyk/kambi/blob/main/api/app/boards/service.py) (Board management), [`web/src/pages/BoardPage.tsx`](https://github.com/fcherchyk/kambi/blob/main/web/src/pages/BoardPage.tsx) (Board workspace), [`api/app/main.py`](https://github.com/fcherchyk/kambi/blob/main/api/app/main.py) (FastAPI app)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ui["Web interface"]
  node_app["SPA shell<br/>[App.tsx]"]
  node_boards_ui["Boards list<br/>[BoardsPage.tsx]"]
  node_board_ui["Board workspace<br/>[BoardPage.tsx]"]
  node_board_state["Board state<br/>[useBoard.ts]"]
  node_column_view["Column and cards<br/>[ColumnView.tsx]"]
  node_archive_ui["Archive view<br/>[ArchivePage.tsx]"]
  node_card_types_ui["Card types panel<br/>[CardTypesPanel.tsx]"]
  node_keyboard["Keyboard shortcuts<br/>[shortcuts.ts]"]
  node_api_client["API client<br/>[client.ts]"]
end

subgraph group_api["API and authentication"]
  node_api_app["FastAPI app<br/>[main.py]"]
  node_auth_flow["Google sign-in<br/>[google.py]"]
  node_auth_sessions["Sessions and identity<br/>[sessions.py]"]
  node_auth_gate["Request authentication<br/>[dependencies.py]"]
end

subgraph group_domain["Board domain"]
  node_boards["Board management<br/>[service.py]"]
  node_columns["Column lifecycle<br/>[service.py]"]
  node_cards["Card lifecycle<br/>[service.py]"]
  node_card_types["Card type rules<br/>[service.py]"]
  node_ordering["Fractional ordering<br/>[ordering.py]"]
end

subgraph group_storage["Persistence"]
  node_db["Database sessions<br/>[db.py]"]
  node_board_models["Board records<br/>[models.py]"]
  node_card_models["Card records<br/>[models.py]"]
  node_column_models["Column records<br/>[models.py]"]
  node_type_models["Card type records<br/>[models.py]"]
  node_auth_models["User and sessions<br/>[models.py]"]
end

subgraph group_external["External services"]
  node_postgres[("PostgreSQL")]
  node_google{{"Google OAuth"}}
end

node_user(("Board user"))

node_user -->|"uses"| node_app
node_app -->|"routes"| node_boards_ui
node_app -->|"routes"| node_board_ui
node_app -->|"routes"| node_archive_ui
node_board_ui -->|"loads state"| node_board_state
node_board_ui -->|"renders"| node_column_view
node_board_ui -->|"renders"| node_card_types_ui
node_board_ui -->|"handles shortcuts"| node_keyboard
node_boards_ui -->|"requests"| node_api_client
node_board_state -->|"requests"| node_api_client
node_column_view -->|"requests"| node_api_client
node_api_client -->|"HTTP requests"| node_api_app
node_api_app -->|"configures"| node_auth_flow
node_api_app -->|"registers"| node_auth_gate
node_api_app -->|"registers routes"| node_boards
node_auth_gate -->|"resolves token"| node_auth_sessions
node_auth_sessions -->|"reads and writes"| node_auth_models
node_auth_flow -->|"OAuth exchange"| node_google
node_boards -->|"reads and writes"| node_board_models
node_boards -->|"seeds and reads"| node_column_models
node_boards -->|"seeds and reads"| node_type_models
node_boards -->|"reads and deletes"| node_card_models
node_columns -->|"reads and writes"| node_column_models
node_columns -->|"moves or deletes"| node_card_models
node_cards -->|"reads and writes"| node_card_models
node_cards -->|"checks columns"| node_columns
node_cards -->|"validates type"| node_card_types
node_card_types -->|"reads and writes"| node_type_models
node_card_types -->|"reassigns cards"| node_card_models
node_boards -->|"generates sort keys"| node_ordering
node_columns -->|"generates sort keys"| node_ordering
node_cards -->|"generates sort keys"| node_ordering
node_api_app -->|"creates sessions"| node_db
node_db -->|"connects"| node_postgres
node_auth_sessions -->|"uses session"| node_db
node_board_models -->|"maps records"| node_db
node_card_models -->|"maps records"| node_db
node_column_models -->|"maps records"| node_db
node_type_models -->|"maps records"| node_db
node_auth_models -->|"maps records"| node_db
node_archive_ui -.->|"loads archive"| node_api_client

click node_app "https://github.com/fcherchyk/kambi/blob/main/web/src/App.tsx"
click node_boards_ui "https://github.com/fcherchyk/kambi/blob/main/web/src/pages/BoardsPage.tsx"
click node_board_ui "https://github.com/fcherchyk/kambi/blob/main/web/src/pages/BoardPage.tsx"
click node_board_state "https://github.com/fcherchyk/kambi/blob/main/web/src/board/useBoard.ts"
click node_column_view "https://github.com/fcherchyk/kambi/blob/main/web/src/board/ColumnView.tsx"
click node_archive_ui "https://github.com/fcherchyk/kambi/blob/main/web/src/pages/ArchivePage.tsx"
click node_card_types_ui "https://github.com/fcherchyk/kambi/blob/main/web/src/board/CardTypesPanel.tsx"
click node_keyboard "https://github.com/fcherchyk/kambi/blob/main/web/src/keyboard/shortcuts.ts"
click node_api_client "https://github.com/fcherchyk/kambi/blob/main/web/src/api/client.ts"
click node_api_app "https://github.com/fcherchyk/kambi/blob/main/api/app/main.py"
click node_auth_flow "https://github.com/fcherchyk/kambi/blob/main/api/app/auth/google.py"
click node_auth_sessions "https://github.com/fcherchyk/kambi/blob/main/api/app/auth/sessions.py"
click node_auth_gate "https://github.com/fcherchyk/kambi/blob/main/api/app/auth/dependencies.py"
click node_boards "https://github.com/fcherchyk/kambi/blob/main/api/app/boards/service.py"
click node_columns "https://github.com/fcherchyk/kambi/blob/main/api/app/columns/service.py"
click node_cards "https://github.com/fcherchyk/kambi/blob/main/api/app/cards/service.py"
click node_card_types "https://github.com/fcherchyk/kambi/blob/main/api/app/card_types/service.py"
click node_ordering "https://github.com/fcherchyk/kambi/blob/main/api/app/ordering.py"
click node_db "https://github.com/fcherchyk/kambi/blob/main/api/app/db.py"
click node_board_models "https://github.com/fcherchyk/kambi/blob/main/api/app/boards/models.py"
click node_card_models "https://github.com/fcherchyk/kambi/blob/main/api/app/cards/models.py"
click node_column_models "https://github.com/fcherchyk/kambi/blob/main/api/app/columns/models.py"
click node_type_models "https://github.com/fcherchyk/kambi/blob/main/api/app/card_types/models.py"
click node_auth_models "https://github.com/fcherchyk/kambi/blob/main/api/app/auth/models.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_app,node_boards_ui,node_board_ui,node_board_state,node_column_view,node_archive_ui,node_card_types_ui,node_keyboard,node_api_client,node_user toneBlue
class node_api_app,node_auth_flow,node_auth_sessions,node_auth_gate toneAmber
class node_boards,node_columns,node_cards,node_card_types,node_ordering toneMint
class node_db,node_board_models,node_card_models,node_column_models,node_type_models,node_auth_models toneRose
class node_postgres,node_google toneIndigo
```

## Components

### Web interface

- [SPA shell](https://github.com/fcherchyk/kambi/blob/main/web/src/App.tsx): `web/src/App.tsx`
- [Boards list](https://github.com/fcherchyk/kambi/blob/main/web/src/pages/BoardsPage.tsx): `web/src/pages/BoardsPage.tsx`
- [Board workspace](https://github.com/fcherchyk/kambi/blob/main/web/src/pages/BoardPage.tsx): `web/src/pages/BoardPage.tsx`
- [Board state](https://github.com/fcherchyk/kambi/blob/main/web/src/board/useBoard.ts): `web/src/board/useBoard.ts`
- [Column and cards](https://github.com/fcherchyk/kambi/blob/main/web/src/board/ColumnView.tsx): `web/src/board/ColumnView.tsx`
- [Archive view](https://github.com/fcherchyk/kambi/blob/main/web/src/pages/ArchivePage.tsx): `web/src/pages/ArchivePage.tsx`
- [Card types panel](https://github.com/fcherchyk/kambi/blob/main/web/src/board/CardTypesPanel.tsx): `web/src/board/CardTypesPanel.tsx`
- [Keyboard shortcuts](https://github.com/fcherchyk/kambi/blob/main/web/src/keyboard/shortcuts.ts): `web/src/keyboard/shortcuts.ts`
- [API client](https://github.com/fcherchyk/kambi/blob/main/web/src/api/client.ts): `web/src/api/client.ts`

### API and authentication

- [FastAPI app](https://github.com/fcherchyk/kambi/blob/main/api/app/main.py): `api/app/main.py`
- [Google sign-in](https://github.com/fcherchyk/kambi/blob/main/api/app/auth/google.py): `api/app/auth/google.py`
- [Sessions and identity](https://github.com/fcherchyk/kambi/blob/main/api/app/auth/sessions.py): `api/app/auth/sessions.py`
- [Request authentication](https://github.com/fcherchyk/kambi/blob/main/api/app/auth/dependencies.py): `api/app/auth/dependencies.py`

### Board domain

- [Board management](https://github.com/fcherchyk/kambi/blob/main/api/app/boards/service.py): `api/app/boards/service.py`
- [Column lifecycle](https://github.com/fcherchyk/kambi/blob/main/api/app/columns/service.py): `api/app/columns/service.py`
- [Card lifecycle](https://github.com/fcherchyk/kambi/blob/main/api/app/cards/service.py): `api/app/cards/service.py`
- [Card type rules](https://github.com/fcherchyk/kambi/blob/main/api/app/card_types/service.py): `api/app/card_types/service.py`
- [Fractional ordering](https://github.com/fcherchyk/kambi/blob/main/api/app/ordering.py): `api/app/ordering.py`

### Persistence

- [Database sessions](https://github.com/fcherchyk/kambi/blob/main/api/app/db.py): `api/app/db.py`
- [Board records](https://github.com/fcherchyk/kambi/blob/main/api/app/boards/models.py): `api/app/boards/models.py`
- [Card records](https://github.com/fcherchyk/kambi/blob/main/api/app/cards/models.py): `api/app/cards/models.py`
- [Column records](https://github.com/fcherchyk/kambi/blob/main/api/app/columns/models.py): `api/app/columns/models.py`
- [Card type records](https://github.com/fcherchyk/kambi/blob/main/api/app/card_types/models.py): `api/app/card_types/models.py`
- [User and sessions](https://github.com/fcherchyk/kambi/blob/main/api/app/auth/models.py): `api/app/auth/models.py`

### External services

- **PostgreSQL**
- **Google OAuth**

### Other components

- **Board user**

## Connections

- Board user → SPA shell: uses
- SPA shell → Boards list: routes (evidence: `web/src/App.tsx`)
- SPA shell → Board workspace: routes (evidence: `web/src/App.tsx`)
- SPA shell → Archive view: routes (evidence: `web/src/App.tsx`)
- Board workspace → Board state: loads state (evidence: `web/src/pages/BoardPage.tsx`)
- Board workspace → Column and cards: renders (evidence: `web/src/pages/BoardPage.tsx`)
- Board workspace → Card types panel: renders (evidence: `web/src/pages/BoardPage.tsx`)
- Board workspace → Keyboard shortcuts: handles shortcuts (evidence: `web/src/pages/BoardPage.tsx`)
- Boards list → API client: requests (evidence: `web/src/pages/BoardsPage.tsx`)
- Board state → API client: requests (evidence: `web/src/board/useBoard.ts`)
- Column and cards → API client: requests (evidence: `web/src/board/ColumnView.tsx`)
- API client → FastAPI app: HTTP requests
- FastAPI app → Google sign-in: configures (evidence: `api/app/main.py`)
- FastAPI app → Request authentication: registers (evidence: `api/app/main.py`)
- FastAPI app → Board management: registers routes (evidence: `api/app/main.py`)
- Request authentication → Sessions and identity: resolves token (evidence: `api/app/auth/dependencies.py`)
- Sessions and identity → User and sessions: reads and writes (evidence: `api/app/auth/sessions.py`)
- Google sign-in → Google OAuth: OAuth exchange
- Board management → Board records: reads and writes (evidence: `api/app/boards/service.py`)
- Board management → Column records: seeds and reads (evidence: `api/app/boards/service.py`)
- Board management → Card type records: seeds and reads (evidence: `api/app/boards/service.py`)
- Board management → Card records: reads and deletes (evidence: `api/app/boards/service.py`)
- Column lifecycle → Column records: reads and writes (evidence: `api/app/columns/service.py`)
- Column lifecycle → Card records: moves or deletes (evidence: `api/app/columns/service.py`)
- Card lifecycle → Card records: reads and writes (evidence: `api/app/cards/service.py`)
- Card lifecycle → Column lifecycle: checks columns (evidence: `api/app/cards/service.py`)
- Card lifecycle → Card type rules: validates type (evidence: `api/app/cards/service.py`)
- Card type rules → Card type records: reads and writes (evidence: `api/app/card_types/service.py`)
- Card type rules → Card records: reassigns cards (evidence: `api/app/card_types/service.py`)
- Board management → Fractional ordering: generates sort keys (evidence: `api/app/boards/service.py`)
- Column lifecycle → Fractional ordering: generates sort keys (evidence: `api/app/columns/service.py`)
- Card lifecycle → Fractional ordering: generates sort keys (evidence: `api/app/cards/service.py`)
- FastAPI app → Database sessions: creates sessions (evidence: `api/app/main.py`)
- Database sessions → PostgreSQL: connects
- Sessions and identity → Database sessions: uses session (evidence: `api/app/auth/sessions.py`)
- Board records → Database sessions: maps records (evidence: `api/app/boards/models.py`)
- Card records → Database sessions: maps records (evidence: `api/app/cards/models.py`)
- Column records → Database sessions: maps records (evidence: `api/app/columns/models.py`)
- Card type records → Database sessions: maps records (evidence: `api/app/card_types/models.py`)
- User and sessions → Database sessions: maps records (evidence: `api/app/auth/models.py`)
- Archive view → API client: loads archive
