# felpau05/grocery-store-deal-tracker architecture

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

- Interactive diagram: https://gitdiagram.com/felpau05/grocery-store-deal-tracker
- Repository: https://github.com/felpau05/grocery-store-deal-tracker

## Overview

Grocery-Store-Deal-Tracker collects regional flyer data, normalizes it into searchable deals and price history, and lets shoppers compare prices and plan multi-store trips. The principal flow runs from the browser through the Next.js client and FastAPI routes to Postgres; preference changes can trigger the separate Go scraper, which fetches and parses Flipp data for storage. Python classifies uncategorized scraped items asynchronously. The graph preserves documented auth, cart, history, and optimization capabilities; some frontend and route wiring is based on README descriptions because those sources were not sampled.

Main entry points: [`backend/main.py`](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/main.py) (FastAPI app), [`frontend/src/lib/api.ts`](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/lib/api.ts) (API client), [`scraper-go/scrape.go`](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/scrape.go) (Scrape runner), [`backend/classifier/backfill.py`](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/classifier/backfill.py) (Classification backfill)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Shopper experience"]
  node_frontend["Next.js app<br/>[page.tsx]"]
  node_frontend_api["API client<br/>[api.ts]"]
  node_deal_pages["Deals and history<br/>[page.tsx]"]
  node_list_page["Shopping list<br/>[page.tsx]"]
  node_settings_page["Settings<br/>[page.tsx]"]
end

subgraph group_api["API and accounts"]
  node_api_app["FastAPI app<br/>[main.py]"]
  node_deal_routes["Deal routes<br/>[deals.py]"]
  node_auth_routes["Auth and preferences<br/>[auth.py]"]
  node_cart_routes["Cart routes<br/>[cart.py]"]
  node_optimize_routes["Optimization routes<br/>[optimize.py]"]
  node_scraper_client["Scraper client<br/>[scraper_client.py]"]
end

subgraph group_ingestion["Flyer ingestion"]
  node_scraper_server["Scraper job API<br/>[server.go]"]
  node_scrape_job["Job coordination<br/>[job.go]"]
  node_scrape_run["Scrape runner<br/>[scrape.go]"]
  node_flipp_client["Flyer fetcher<br/>[client.go]"]
  node_parser["Item parser<br/>[pipeline.go]"]
end

subgraph group_data["Deal data"]
  node_postgres[("Postgres")]
  node_deal_queries["Deal and history reads<br/>[queries.py]"]
  node_item_store["Item persistence<br/>[items.py]"]
  node_cart_store["Cart persistence<br/>[cart.py]"]
  node_user_store["User persistence<br/>[users.py]"]
end

subgraph group_planning["Classification and planning"]
  node_classifier["Classifier<br/>[classify.py]"]
  node_backfill["Classification backfill<br/>[backfill.py]"]
  node_optimizer["Trip optimizer<br/>[algorithm.py]"]
end

node_shopper(("Shopper"))
node_flipp["Flipp API"]
node_redis[("Redis")]

node_shopper -->|"uses"| node_frontend
node_frontend -->|"requests data"| node_frontend_api
node_frontend_api -->|"calls API"| node_api_app
node_deal_pages -->|"loads deals"| node_frontend_api
node_list_page -->|"submits list"| node_frontend_api
node_settings_page -->|"saves preferences"| node_frontend_api
node_api_app -->|"registers"| node_deal_routes
node_api_app -->|"registers"| node_auth_routes
node_api_app -->|"registers"| node_cart_routes
node_api_app -->|"registers"| node_optimize_routes
node_deal_routes -->|"queries"| node_deal_queries
node_deal_queries -->|"reads deals and history"| node_postgres
node_auth_routes -->|"reads and writes"| node_user_store
node_user_store -->|"reads and writes"| node_postgres
node_cart_routes -->|"reads and writes"| node_cart_store
node_cart_store -->|"reads and writes"| node_postgres
node_auth_routes -->|"triggers scrape"| node_scraper_client
node_scraper_client -->|"starts and polls jobs"| node_scraper_server
node_scraper_client -.->|"caches job IDs"| node_redis
node_scraper_server -->|"claims and tracks"| node_scrape_job
node_scrape_job -->|"locks and stores jobs"| node_redis
node_scraper_server -->|"runs asynchronously"| node_scrape_run
node_scrape_run -->|"fetches flyer data"| node_flipp_client
node_flipp_client -->|"requests flyers and items"| node_flipp
node_scrape_run -->|"normalizes items"| node_parser
node_scrape_run -->|"persists items"| node_item_store
node_item_store -->|"writes items"| node_postgres
node_optimize_routes -->|"optimizes list"| node_optimizer
node_optimize_routes -->|"loads deal data"| node_deal_queries
node_api_app -->|"starts scheduler"| node_backfill
node_backfill -->|"reads uncategorized items"| node_postgres
node_backfill -->|"classifies batches"| node_classifier
node_backfill -->|"updates categories"| node_item_store

click node_frontend "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/app/page.tsx"
click node_frontend_api "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/lib/api.ts"
click node_deal_pages "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/app/deals/page.tsx"
click node_list_page "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/app/list/page.tsx"
click node_settings_page "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/app/settings/page.tsx"
click node_api_app "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/main.py"
click node_deal_routes "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/routes/deals.py"
click node_auth_routes "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/routes/auth.py"
click node_cart_routes "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/routes/cart.py"
click node_optimize_routes "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/routes/optimize.py"
click node_scraper_client "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/scraper_client.py"
click node_scraper_server "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/server.go"
click node_scrape_job "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/job.go"
click node_scrape_run "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/scrape.go"
click node_flipp_client "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/client.go"
click node_parser "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/pipeline.go"
click node_deal_queries "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/db/queries.py"
click node_item_store "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/db/items.py"
click node_cart_store "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/db/cart.py"
click node_user_store "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/db/users.py"
click node_classifier "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/classifier/classify.py"
click node_backfill "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/classifier/backfill.py"
click node_optimizer "https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/optimizer/algorithm.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_frontend,node_frontend_api,node_deal_pages,node_list_page,node_settings_page toneBlue
class node_api_app,node_deal_routes,node_auth_routes,node_cart_routes,node_optimize_routes,node_scraper_client,node_redis toneAmber
class node_scraper_server,node_scrape_job,node_scrape_run,node_flipp_client,node_parser,node_flipp toneMint
class node_postgres,node_deal_queries,node_item_store,node_cart_store,node_user_store toneRose
class node_classifier,node_backfill,node_optimizer,node_shopper toneIndigo
```

## Components

### Shopper experience

- [Next.js app](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/app/page.tsx): `frontend/src/app/page.tsx`
- [API client](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/lib/api.ts): `frontend/src/lib/api.ts`
- [Deals and history](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/app/deals/page.tsx): `frontend/src/app/deals/page.tsx`
- [Shopping list](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/app/list/page.tsx): `frontend/src/app/list/page.tsx`
- [Settings](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/frontend/src/app/settings/page.tsx): `frontend/src/app/settings/page.tsx`

### API and accounts

- [FastAPI app](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/main.py): `backend/main.py`
- [Deal routes](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/routes/deals.py): `backend/routes/deals.py`
- [Auth and preferences](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/routes/auth.py): `backend/routes/auth.py`
- [Cart routes](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/routes/cart.py): `backend/routes/cart.py`
- [Optimization routes](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/routes/optimize.py): `backend/routes/optimize.py`
- [Scraper client](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/scraper_client.py): `backend/scraper_client.py`

### Flyer ingestion

- [Scraper job API](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/server.go): `scraper-go/server.go`
- [Job coordination](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/job.go): `scraper-go/job.go`
- [Scrape runner](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/scrape.go): `scraper-go/scrape.go`
- [Flyer fetcher](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/client.go): `scraper-go/client.go`
- [Item parser](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/scraper-go/pipeline.go): `scraper-go/pipeline.go`

### Deal data

- **Postgres**
- [Deal and history reads](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/db/queries.py): `backend/db/queries.py`
- [Item persistence](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/db/items.py): `backend/db/items.py`
- [Cart persistence](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/db/cart.py): `backend/db/cart.py`
- [User persistence](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/db/users.py): `backend/db/users.py`

### Classification and planning

- [Classifier](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/classifier/classify.py): `backend/classifier/classify.py`
- [Classification backfill](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/classifier/backfill.py): `backend/classifier/backfill.py`
- [Trip optimizer](https://github.com/felpau05/grocery-store-deal-tracker/blob/main/backend/optimizer/algorithm.py): `backend/optimizer/algorithm.py`

### Other components

- **Shopper**
- **Flipp API**
- **Redis**

## Connections

- Shopper → Next.js app: uses
- Next.js app → API client: requests data
- API client → FastAPI app: calls API
- Deals and history → API client: loads deals
- Shopping list → API client: submits list
- Settings → API client: saves preferences
- FastAPI app → Deal routes: registers
- FastAPI app → Auth and preferences: registers
- FastAPI app → Cart routes: registers
- FastAPI app → Optimization routes: registers
- Deal routes → Deal and history reads: queries
- Deal and history reads → Postgres: reads deals and history
- Auth and preferences → User persistence: reads and writes
- User persistence → Postgres: reads and writes
- Cart routes → Cart persistence: reads and writes
- Cart persistence → Postgres: reads and writes
- Auth and preferences → Scraper client: triggers scrape
- Scraper client → Scraper job API: starts and polls jobs
- Scraper client → Redis: caches job IDs
- Scraper job API → Job coordination: claims and tracks
- Job coordination → Redis: locks and stores jobs
- Scraper job API → Scrape runner: runs asynchronously
- Scrape runner → Flyer fetcher: fetches flyer data
- Flyer fetcher → Flipp API: requests flyers and items
- Scrape runner → Item parser: normalizes items
- Scrape runner → Item persistence: persists items
- Item persistence → Postgres: writes items
- Optimization routes → Trip optimizer: optimizes list
- Optimization routes → Deal and history reads: loads deal data
- FastAPI app → Classification backfill: starts scheduler
- Classification backfill → Postgres: reads uncategorized items
- Classification backfill → Classifier: classifies batches
- Classification backfill → Item persistence: updates categories
