# ait0xin/carousell-vvip-catalogue-studio architecture

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

- Interactive diagram: https://gitdiagram.com/ait0xin/carousell-vvip-catalogue-studio
- Repository: https://github.com/ait0xin/carousell-vvip-catalogue-studio

## Overview

VVIP Catalogue Studio is a local Streamlit app for checking and rebuilding Carousell merchant catalogues. Users upload a catalogue PDF and VVIP master sheet, review cross-check and QR findings, approve proposed changes, then generate a corrected PDF. The graph preserves the separate extraction, matching, verification, and card-building stages, plus the app’s session state and background-thread runner. The README documents the main wiring; some engine internals were not sampled, so uncertain call links are omitted.

Main entry points: [`app.py`](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/app.py) (Streamlit app), [`studio/generate.py`](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/generate.py) (Approved generation), [`studio/qr.py`](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/qr.py) (QR check), [`studio/crosscheck.py`](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/crosscheck.py) (Cross-check)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ui["Studio UI"]
  node_app["Streamlit app<br/>[app.py]"]
end

subgraph group_checks["Catalogue Checks"]
  node_crosscheck["Cross-check<br/>[crosscheck.py]"]
  node_extract["PDF extraction<br/>[extract.py]"]
  node_master["Master ingest<br/>[ingest.py]"]
  node_normalize["Handle normalization<br/>[normalize.py]"]
  node_qrflow["QR check<br/>[qr.py]"]
  node_decode["QR decoding"]
  node_verify["Live verification<br/>[carousell.py]"]
  node_preview["Annotated preview<br/>[preview.py]"]
end

subgraph group_build["Catalogue Building"]
  node_generate["Approved generation<br/>[generate.py]"]
  node_profile["Profile fetching<br/>[fetcher.py]"]
  node_http_profile["HTTP profile fetch<br/>[profile_http.py]"]
  node_describe["Merchant descriptions<br/>[describer.py]"]
  node_qrgen["QR generation<br/>[qrgen.py]"]
  node_render["PDF rendering<br/>[pdf_render.py]"]
end

subgraph group_runtime["Shared Runtime"]
  node_session["Session state<br/>[state.py]"]
  node_sources["Engine wiring<br/>[sources.py]"]
  node_runner["Background runner<br/>[runner.py]"]
end

node_user(("Catalogue editor"))
node_pdf["Corrected catalogue"]
node_masterfile["VVIP master sheet"]
node_carousell["Carousell profiles"]
node_ai["Configured AI provider"]

node_user -->|"uploads and reviews"| node_app
node_app -->|"updates state"| node_session
node_app -->|"wires engines"| node_sources
node_app -->|"runs check"| node_crosscheck
node_app -->|"runs check"| node_qrflow
node_app -->|"runs approved build"| node_generate
node_app -->|"dispatches stages"| node_runner
node_masterfile -->|"uploaded to"| node_app
node_pdf -->|"uploaded to"| node_app
node_crosscheck -->|"extracts catalogue"| node_extract
node_crosscheck -->|"loads master"| node_master
node_masterfile -->|"ingested by"| node_master
node_extract -->|"normalizes handles"| node_normalize
node_master -->|"normalizes handles"| node_normalize
node_crosscheck -->|"stores findings"| node_session
node_qrflow -->|"extracts QR rows"| node_extract
node_qrflow -->|"decodes QR codes"| node_decode
node_qrflow -->|"checks live profiles"| node_verify
node_verify -->|"renders profiles"| node_carousell
node_qrflow -->|"stores verdicts"| node_session
node_app -->|"shows annotations"| node_preview
node_generate -->|"reads approvals"| node_session
node_generate -->|"fetches merchant data"| node_profile
node_profile -->|"fetches profiles"| node_carousell
node_generate -.->|"may fetch profiles"| node_http_profile
node_http_profile -.->|"fetches profiles"| node_carousell
node_generate -->|"creates descriptions"| node_describe
node_describe -.->|"requests descriptions"| node_ai
node_generate -->|"creates fresh QR"| node_qrgen
node_generate -->|"renders edition"| node_render
node_render -->|"writes PDF"| node_pdf
node_generate -->|"dispatches threaded stage"| node_runner

click node_app "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/app.py"
click node_session "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/state.py"
click node_sources "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/sources.py"
click node_runner "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/runner.py"
click node_crosscheck "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/crosscheck.py"
click node_extract "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/extract.py"
click node_master "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/ingest.py"
click node_normalize "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/normalize.py"
click node_qrflow "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/qr.py"
click node_decode "https://github.com/ait0xin/carousell-vvip-catalogue-studio/tree/main/qrcheck"
click node_verify "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/verify/carousell.py"
click node_preview "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/preview.py"
click node_generate "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/generate.py"
click node_profile "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/catbuilder/fetcher.py"
click node_http_profile "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/profile_http.py"
click node_describe "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/catbuilder/describer.py"
click node_qrgen "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/catbuilder/qrgen.py"
click node_render "https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/catbuilder/pdf_render.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 toneBlue
class node_crosscheck,node_extract,node_master,node_normalize,node_qrflow,node_decode,node_verify,node_preview toneAmber
class node_generate,node_profile,node_http_profile,node_describe,node_qrgen,node_render toneMint
class node_session,node_sources,node_runner toneRose
class node_user,node_pdf,node_masterfile,node_carousell,node_ai toneIndigo
```

## Components

### Studio UI

- [Streamlit app](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/app.py): `app.py`

### Catalogue Checks

- [Cross-check](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/crosscheck.py): `studio/crosscheck.py`
- [PDF extraction](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/extract.py): `qrcheck/extract.py`
- [Master ingest](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/ingest.py): `qrcheck/ingest.py`
- [Handle normalization](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/normalize.py): `qrcheck/normalize.py`
- [QR check](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/qr.py): `studio/qr.py`
- [QR decoding](https://github.com/ait0xin/carousell-vvip-catalogue-studio/tree/main/qrcheck): `qrcheck`
- [Live verification](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/verify/carousell.py): `qrcheck/verify/carousell.py`
- [Annotated preview](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/qrcheck/preview.py): `qrcheck/preview.py`

### Catalogue Building

- [Approved generation](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/generate.py): `studio/generate.py`
- [Profile fetching](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/catbuilder/fetcher.py): `catbuilder/fetcher.py`
- [HTTP profile fetch](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/profile_http.py): `studio/profile_http.py`
- [Merchant descriptions](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/catbuilder/describer.py): `catbuilder/describer.py`
- [QR generation](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/catbuilder/qrgen.py): `catbuilder/qrgen.py`
- [PDF rendering](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/catbuilder/pdf_render.py): `catbuilder/pdf_render.py`

### Shared Runtime

- [Session state](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/state.py): `studio/state.py`
- [Engine wiring](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/sources.py): `studio/sources.py`
- [Background runner](https://github.com/ait0xin/carousell-vvip-catalogue-studio/blob/main/studio/runner.py): `studio/runner.py`

### Other components

- **Catalogue editor**
- **Corrected catalogue**
- **VVIP master sheet**
- **Carousell profiles**
- **Configured AI provider**

## Connections

- Catalogue editor → Streamlit app: uploads and reviews
- Streamlit app → Session state: updates state
- Streamlit app → Engine wiring: wires engines
- Streamlit app → Cross-check: runs check
- Streamlit app → QR check: runs check
- Streamlit app → Approved generation: runs approved build
- Streamlit app → Background runner: dispatches stages
- VVIP master sheet → Streamlit app: uploaded to
- Corrected catalogue → Streamlit app: uploaded to
- Cross-check → PDF extraction: extracts catalogue
- Cross-check → Master ingest: loads master
- VVIP master sheet → Master ingest: ingested by
- PDF extraction → Handle normalization: normalizes handles
- Master ingest → Handle normalization: normalizes handles
- Cross-check → Session state: stores findings
- QR check → PDF extraction: extracts QR rows
- QR check → QR decoding: decodes QR codes
- QR check → Live verification: checks live profiles
- Live verification → Carousell profiles: renders profiles
- QR check → Session state: stores verdicts
- Streamlit app → Annotated preview: shows annotations
- Approved generation → Session state: reads approvals
- Approved generation → Profile fetching: fetches merchant data
- Profile fetching → Carousell profiles: fetches profiles
- Approved generation → HTTP profile fetch: may fetch profiles
- HTTP profile fetch → Carousell profiles: fetches profiles
- Approved generation → Merchant descriptions: creates descriptions
- Merchant descriptions → Configured AI provider: requests descriptions
- Approved generation → QR generation: creates fresh QR
- Approved generation → PDF rendering: renders edition
- PDF rendering → Corrected catalogue: writes PDF
- Approved generation → Background runner: dispatches threaded stage
