# kairothq/claude-photo-sorter architecture

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

- Interactive diagram: https://gitdiagram.com/kairothq/claude-photo-sorter
- Repository: https://github.com/kairothq/claude-photo-sorter

## Overview

Claude Photo Sorter is a local photo/video organizer. The main workflow starts in the dashboard, which calls a loopback-only Python API; the server coordinates scanning, duplicate detection, labeling, and copy-based output. Users can review and move items through the dashboard, which also supports category editing and a demo. The workflow’s core modules and both labelers are evidenced in the supplied source; several dashboard API interactions are only partly excerpted, so those links use the visible API references or README documentation.

Main entry points: [`scripts/server.py`](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/server.py) (Local API server), [`dashboard/app.js`](https://github.com/kairothq/claude-photo-sorter/blob/main/dashboard/app.js) (Sort dashboard), [`scripts/apply.py`](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/apply.py) (Build sorted copies), [`scripts/label_claude.py`](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/label_claude.py) (Claude labeler)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_interface["Dashboard"]
  node_dashboard["Sort dashboard<br/>[app.js]"]
end

subgraph group_orchestration["Local API"]
  node_server["Local API server<br/>[server.py]"]
end

subgraph group_processing["Sort processing"]
  node_scan["Scan media<br/>[scan.py]"]
  node_dupes["Find duplicates<br/>[dupes.py]"]
  node_sheets["Contact sheets<br/>[sheets.py]"]
  node_apply["Build sorted copies<br/>[apply.py]"]
  node_shared["Paths and JSON<br/>[common.py]"]
  node_demo["Demo generator<br/>[demo.py]"]
end

subgraph group_labeling["Label providers"]
  node_claude["Claude labeler<br/>[label_claude.py]"]
  node_jev["Jev labeler<br/>[label_jev.py]"]
end

node_user(("User"))
node_claude_service{{"Claude Code"}}
node_jev_service{{"TypeSafe Jev"}}
node_photos["Photo folder"]
node_output["Sorted folders"]
node_state[("Local sort data")]
node_categories["Folder categories<br/>[categories.json]"]

node_user -->|"chooses and starts"| node_dashboard
node_dashboard -->|"calls local API"| node_server
node_server -->|"dispatches scan"| node_scan
node_server -->|"dispatches duplicates"| node_dupes
node_server -->|"dispatches labels"| node_claude
node_server -->|"dispatches labels"| node_jev
node_server -->|"dispatches output"| node_apply
node_scan -->|"reads originals"| node_photos
node_scan -->|"writes inventory previews"| node_state
node_dupes -->|"reads inventory previews; writes groups"| node_state
node_claude -->|"runs when absent"| node_sheets
node_sheets -->|"reads previews inventory"| node_state
node_claude -->|"requests labels"| node_claude_service
node_claude -->|"reads sheets inventory; saves labels"| node_state
node_jev -->|"sends previews"| node_jev_service
node_jev -->|"reads previews inventory; saves labels"| node_state
node_apply -->|"reads labels duplicates"| node_state
node_apply -->|"reads categories"| node_categories
node_apply -->|"copies files; writes reports"| node_output
node_server -->|"updates categories"| node_categories
node_server -.->|"serves sort state"| node_state
node_dashboard -.->|"supports demo mode"| node_demo
node_demo -->|"generates sample data"| node_state
node_shared -->|"defines storage paths"| node_state
node_dashboard -.->|"browses and opens results"| node_output

click node_dashboard "https://github.com/kairothq/claude-photo-sorter/blob/main/dashboard/app.js"
click node_server "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/server.py"
click node_scan "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/scan.py"
click node_dupes "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/dupes.py"
click node_sheets "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/sheets.py"
click node_apply "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/apply.py"
click node_shared "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/common.py"
click node_claude "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/label_claude.py"
click node_jev "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/label_jev.py"
click node_categories "https://github.com/kairothq/claude-photo-sorter/blob/main/categories.json"
click node_demo "https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/demo.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_dashboard,node_user toneBlue
class node_server,node_state toneAmber
class node_scan,node_dupes,node_sheets,node_apply,node_shared,node_demo toneMint
class node_claude,node_jev toneRose
class node_claude_service,node_jev_service,node_photos,node_output toneIndigo
class node_categories toneTeal
```

## Components

### Dashboard

- [Sort dashboard](https://github.com/kairothq/claude-photo-sorter/blob/main/dashboard/app.js): `dashboard/app.js`

### Local API

- [Local API server](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/server.py): `scripts/server.py`

### Sort processing

- [Scan media](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/scan.py): `scripts/scan.py`
- [Find duplicates](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/dupes.py): `scripts/dupes.py`
- [Contact sheets](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/sheets.py): `scripts/sheets.py`
- [Build sorted copies](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/apply.py): `scripts/apply.py`
- [Paths and JSON](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/common.py): `scripts/common.py`
- [Demo generator](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/demo.py): `scripts/demo.py`

### Label providers

- [Claude labeler](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/label_claude.py): `scripts/label_claude.py`
- [Jev labeler](https://github.com/kairothq/claude-photo-sorter/blob/main/scripts/label_jev.py): `scripts/label_jev.py`

### Other components

- **User**
- **Claude Code**
- **TypeSafe Jev**
- **Photo folder**
- **Sorted folders**
- **Local sort data**
- [Folder categories](https://github.com/kairothq/claude-photo-sorter/blob/main/categories.json): `categories.json`

## Connections

- User → Sort dashboard: chooses and starts (evidence: `README.md`)
- Sort dashboard → Local API server: calls local API (evidence: `dashboard/app.js`)
- Local API server → Scan media: dispatches scan (evidence: `scripts/server.py`)
- Local API server → Find duplicates: dispatches duplicates (evidence: `scripts/server.py`)
- Local API server → Claude labeler: dispatches labels (evidence: `scripts/server.py`)
- Local API server → Jev labeler: dispatches labels (evidence: `scripts/server.py`)
- Local API server → Build sorted copies: dispatches output (evidence: `scripts/server.py`)
- Scan media → Photo folder: reads originals (evidence: `scripts/scan.py`)
- Scan media → Local sort data: writes inventory previews (evidence: `scripts/scan.py`)
- Find duplicates → Local sort data: reads inventory previews; writes groups (evidence: `scripts/dupes.py`)
- Claude labeler → Contact sheets: runs when absent (evidence: `scripts/label_claude.py`)
- Contact sheets → Local sort data: reads previews inventory (evidence: `scripts/sheets.py`)
- Claude labeler → Claude Code: requests labels (evidence: `scripts/label_claude.py`)
- Claude labeler → Local sort data: reads sheets inventory; saves labels (evidence: `scripts/label_claude.py`)
- Jev labeler → TypeSafe Jev: sends previews (evidence: `scripts/label_jev.py`)
- Jev labeler → Local sort data: reads previews inventory; saves labels (evidence: `scripts/label_jev.py`)
- Build sorted copies → Local sort data: reads labels duplicates (evidence: `scripts/apply.py`)
- Build sorted copies → Folder categories: reads categories (evidence: `scripts/apply.py`)
- Build sorted copies → Sorted folders: copies files; writes reports (evidence: `scripts/apply.py`)
- Local API server → Folder categories: updates categories (evidence: `scripts/server.py`)
- Local API server → Local sort data: serves sort state
- Sort dashboard → Demo generator: supports demo mode (evidence: `README.md`)
- Demo generator → Local sort data: generates sample data (evidence: `scripts/demo.py`)
- Paths and JSON → Local sort data: defines storage paths (evidence: `scripts/common.py`)
- Sort dashboard → Sorted folders: browses and opens results (evidence: `README.md`)
