# snappriceaffiliate/photostudio architecture

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

- Interactive diagram: https://gitdiagram.com/snappriceaffiliate/photostudio
- Repository: https://github.com/snappriceaffiliate/photostudio

## Overview

PickSnap is a studio-to-client photo-selection product: studios create events and upload photos; the browser compresses previews and thumbnails while RAW originals stay local; clients open a shared gallery, select photos, add notes, and submit; studios review and export the selection list. Supporting capabilities include studio accounts and staff, branding, billing, audit, notifications, and archive retention. The README documents the main workflow and capabilities; sampled source confirms several frontend/API and storage relationships, but many backend routes were not inspected, so those links are documented rather than inferred from module names.

Main entry points: [`backend/apps/events/views.py`](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/events/views.py) (Event operations), [`frontend/src/pages/StudioPages.tsx`](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/pages/StudioPages.tsx) (Studio screens), [`frontend/src/api/client.ts`](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/api/client.ts) (API client), [`backend/apps/clients/views.py`](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/clients/views.py) (Client access)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_studio["Studio workspace"]
  node_event_domain[("Events and albums<br/>[models.py]")]
  node_event_api["Event operations<br/>[views.py]"]
  node_studio_domain[("Studio tenants<br/>[models.py]")]
end

subgraph group_gallery["Client selection"]
  node_gallery_ui["Client gallery<br/>[GalleryPages.tsx]"]
  node_client_api["Client access<br/>[views.py]"]
  node_selection_data[("Selections and notes<br/>[models.py]")]
  node_exports["Selection exports<br/>[exports.py]"]
end

subgraph group_media["Photo pipeline"]
  node_uploader["Folder uploader<br/>[uploader.ts]"]
  node_compression["Browser compression<br/>[compress.ts]"]
  node_photo_domain[("Photo records<br/>[models.py]")]
  node_photo_api["Photo uploads<br/>[views.py]"]
  node_object_store[("Object storage<br/>[storage.py]")]
end

subgraph group_platform["Platform services"]
  node_accounts["Accounts and staff<br/>[views.py]"]
  node_billing["Plans and payments<br/>[views.py]"]
  node_audit[("Audit trail<br/>[models.py]")]
  node_notifications["Email jobs<br/>[tasks.py]"]
  node_cleanup["Photo retention<br/>[tasks.py]"]
  node_django_api["Django API<br/>[urls.py]"]
end

subgraph group_frontend["Web application"]
  node_studio_ui["Studio screens<br/>[StudioPages.tsx]"]
  node_event_ui["Event workspace<br/>[EventPage.tsx]"]
  node_api_client["API client<br/>[client.ts]"]
  node_app_routes["Application routes<br/>[App.tsx]"]
end

node_studio_owner(("Studio owner"))
node_client(("Gallery client"))

node_studio_owner -->|"manages events"| node_studio_ui
node_studio_ui -->|"opens events"| node_event_ui
node_event_ui -->|"starts uploads"| node_uploader
node_uploader -.->|"compresses images"| node_compression
node_compression -.->|"prepares previews"| node_photo_api
node_event_ui -.->|"sends requests"| node_api_client
node_api_client -->|"calls API"| node_django_api
node_django_api -.->|"routes events"| node_event_api
node_event_api -->|"reads and writes"| node_event_domain
node_event_api -->|"uses photo records"| node_photo_domain
node_photo_api -.->|"uses storage"| node_object_store
node_photo_api -.->|"records uploads"| node_photo_domain
node_client -->|"opens gallery"| node_gallery_ui
node_app_routes -->|"routes gallery"| node_gallery_ui
node_gallery_ui -->|"requests gallery data"| node_api_client
node_api_client -.->|"calls API"| node_client_api
node_client_api -.->|"records selections"| node_selection_data
node_client_api -->|"provides exports"| node_exports
node_studio_ui -.->|"uses staff API"| node_accounts
node_accounts -.->|"manages tenants"| node_studio_domain
node_studio_ui -->|"manages plans"| node_billing
node_event_api -->|"checks entitlements"| node_billing
node_event_api -.->|"records activity"| node_audit
node_accounts -.->|"sends account email"| node_notifications
node_cleanup -->|"deletes old images"| node_object_store
node_cleanup -->|"updates photo records"| node_photo_domain

click node_studio_ui "https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/pages/StudioPages.tsx"
click node_event_ui "https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/pages/EventPage.tsx"
click node_uploader "https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/upload/uploader.ts"
click node_compression "https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/compression/compress.ts"
click node_event_domain "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/events/models.py"
click node_event_api "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/events/views.py"
click node_photo_domain "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/photos/models.py"
click node_photo_api "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/photos/views.py"
click node_object_store "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/core/storage.py"
click node_gallery_ui "https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/gallery/GalleryPages.tsx"
click node_client_api "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/clients/views.py"
click node_selection_data "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/clients/models.py"
click node_exports "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/clients/exports.py"
click node_accounts "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/accounts/views.py"
click node_studio_domain "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/studios/models.py"
click node_billing "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/billing/views.py"
click node_audit "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/audit/models.py"
click node_notifications "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/notifications/tasks.py"
click node_cleanup "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/photos/tasks.py"
click node_api_client "https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/api/client.ts"
click node_app_routes "https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/App.tsx"
click node_django_api "https://github.com/snappriceaffiliate/photostudio/blob/main/backend/config/urls.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_event_domain,node_event_api,node_studio_domain,node_client toneBlue
class node_gallery_ui,node_client_api,node_selection_data,node_exports toneAmber
class node_uploader,node_compression,node_photo_domain,node_photo_api,node_object_store toneMint
class node_accounts,node_billing,node_audit,node_notifications,node_cleanup,node_django_api toneRose
class node_studio_ui,node_event_ui,node_api_client,node_app_routes,node_studio_owner toneIndigo
```

## Components

### Studio workspace

- [Events and albums](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/events/models.py): `backend/apps/events/models.py`
- [Event operations](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/events/views.py): `backend/apps/events/views.py`
- [Studio tenants](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/studios/models.py): `backend/apps/studios/models.py`

### Client selection

- [Client gallery](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/gallery/GalleryPages.tsx): `frontend/src/gallery/GalleryPages.tsx`
- [Client access](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/clients/views.py): `backend/apps/clients/views.py`
- [Selections and notes](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/clients/models.py): `backend/apps/clients/models.py`
- [Selection exports](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/clients/exports.py): `backend/apps/clients/exports.py`

### Photo pipeline

- [Folder uploader](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/upload/uploader.ts): `frontend/src/upload/uploader.ts`
- [Browser compression](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/compression/compress.ts): `frontend/src/compression/compress.ts`
- [Photo records](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/photos/models.py): `backend/apps/photos/models.py`
- [Photo uploads](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/photos/views.py): `backend/apps/photos/views.py`
- [Object storage](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/core/storage.py): `backend/apps/core/storage.py`

### Platform services

- [Accounts and staff](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/accounts/views.py): `backend/apps/accounts/views.py`
- [Plans and payments](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/billing/views.py): `backend/apps/billing/views.py`
- [Audit trail](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/audit/models.py): `backend/apps/audit/models.py`
- [Email jobs](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/notifications/tasks.py): `backend/apps/notifications/tasks.py`
- [Photo retention](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/apps/photos/tasks.py): `backend/apps/photos/tasks.py`
- [Django API](https://github.com/snappriceaffiliate/photostudio/blob/main/backend/config/urls.py): `backend/config/urls.py`

### Web application

- [Studio screens](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/pages/StudioPages.tsx): `frontend/src/pages/StudioPages.tsx`
- [Event workspace](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/pages/EventPage.tsx): `frontend/src/pages/EventPage.tsx`
- [API client](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/api/client.ts): `frontend/src/api/client.ts`
- [Application routes](https://github.com/snappriceaffiliate/photostudio/blob/main/frontend/src/App.tsx): `frontend/src/App.tsx`

### Other components

- **Studio owner**
- **Gallery client**

## Connections

- Studio owner → Studio screens: manages events (evidence: `README.md`)
- Studio screens → Event workspace: opens events (evidence: `frontend/src/App.tsx`)
- Event workspace → Folder uploader: starts uploads (evidence: `frontend/src/pages/EventPage.tsx`)
- Folder uploader → Browser compression: compresses images
- Browser compression → Photo uploads: prepares previews
- Event workspace → API client: sends requests (evidence: `frontend/src/pages/EventPage.tsx`)
- API client → Django API: calls API (evidence: `frontend/src/api/client.ts`)
- Django API → Event operations: routes events (evidence: `backend/config/urls.py`)
- Event operations → Events and albums: reads and writes (evidence: `backend/apps/events/views.py`)
- Event operations → Photo records: uses photo records (evidence: `backend/apps/events/views.py`)
- Photo uploads → Object storage: uses storage
- Photo uploads → Photo records: records uploads
- Gallery client → Client gallery: opens gallery (evidence: `README.md`)
- Application routes → Client gallery: routes gallery (evidence: `frontend/src/App.tsx`)
- Client gallery → API client: requests gallery data (evidence: `frontend/src/gallery/GalleryPages.tsx`)
- API client → Client access: calls API
- Client access → Selections and notes: records selections
- Client access → Selection exports: provides exports (evidence: `README.md`)
- Studio screens → Accounts and staff: uses staff API
- Accounts and staff → Studio tenants: manages tenants
- Studio screens → Plans and payments: manages plans (evidence: `README.md`)
- Event operations → Plans and payments: checks entitlements (evidence: `backend/apps/events/views.py`)
- Event operations → Audit trail: records activity
- Accounts and staff → Email jobs: sends account email
- Photo retention → Object storage: deletes old images (evidence: `backend/apps/photos/tasks.py`)
- Photo retention → Photo records: updates photo records (evidence: `backend/apps/photos/tasks.py`)
