# keejung7/aritziapricetracker architecture

> Architecture diagram of the GitHub repository keejung7/aritziapricetracker, 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/keejung7/aritziapricetracker
- Repository: https://github.com/keejung7/aritziapricetracker

## Overview

Aritzia Price Tracker collects product listings and price/availability observations, stores them in PostgreSQL, and serves a catalog and product-history experience through a Next.js app. The main workflow runs from scraping through raw-data loading and catalog snapshot refresh, then shoppers browse/filter products and inspect price and size history. The README documents the collection and refresh sequence; sampled source confirms key API, service, and UI calls. Some unsampled integrations are therefore omitted rather than inferred.

Main entry points: [`db/db.js`](https://github.com/keejung7/aritziapricetracker/blob/main/db/db.js) (Raw data loader), [`app/components/catalog/CatalogExplorer.tsx`](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/CatalogExplorer.tsx) (Catalog explorer), [`app/components/ProductPriceHistoryExplorer.tsx`](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/ProductPriceHistoryExplorer.tsx) (History explorer), [`app/api/products/[productNo]/price-history/route.ts`](https://github.com/keejung7/aritziapricetracker/blob/main/app/api/products/%5BproductNo%5D/price-history/route.ts) (History API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_collection["Data collection"]
  node_scraper["URL scraper<br/>[scraper.js]"]
  node_details["Detail scraper<br/>[details_scraper.js]"]
  node_view_generator["HTML data view<br/>[generate_view.js]"]
end

subgraph group_storage["Database and catalog"]
  node_loader["Raw data loader<br/>[db.js]"]
  node_parser["Artifact parser<br/>[parser.js]"]
  node_catalog_refresh["Catalog refresh"]
  node_refresh_command["Refresh command"]
  node_postgres[("PostgreSQL")]
  node_catalog_queries["Catalog queries<br/>[catalogQueries.js]"]
  node_history_queries["History queries<br/>[queries.js]"]
end

subgraph group_catalog_ui["Catalog browsing"]
  node_home["Catalog page<br/>[page.tsx]"]
  node_latest["Catalog entry"]
  node_catalog_explorer["Catalog explorer"]
  node_filters["Catalog filters<br/>[CatalogFilters.tsx]"]
  node_catalog_hook["Catalog data hook"]
  node_catalog_api["Catalog API<br/>[route.ts]"]
  node_catalog_service["Catalog service<br/>[catalogService.ts]"]
  node_product_card["Product cards<br/>[ProductCard.tsx]"]
  node_swatches["Color swatches<br/>[ColorSwatches.tsx]"]
  node_sizes["Available sizes<br/>[AvailableSizes.tsx]"]
end

subgraph group_history_ui["Product history"]
  node_product_page["Product page<br/>[page.tsx]"]
  node_history_explorer["History explorer"]
  node_history_api["History API<br/>[route.ts]"]
  node_date_api["Date price API<br/>[route.ts]"]
  node_history_service["History formatter"]
  node_chart_service["Chart history logic"]
  node_price_chart["Price chart"]
  node_availability_chart["Availability chart"]
end

node_aritzia(("Aritzia site"))
node_shopper(("Shopper"))

node_scraper -->|"scrapes categories"| node_aritzia
node_details -->|"scrapes products"| node_aritzia
node_scraper -->|"provides product links"| node_details
node_details -->|"provides JSONL"| node_loader
node_loader -->|"parses input"| node_parser
node_loader -->|"upserts observations"| node_postgres
node_loader -->|"refreshes catalog"| node_catalog_refresh
node_refresh_command -->|"runs refresh"| node_catalog_refresh
node_catalog_refresh -->|"builds snapshots"| node_postgres
node_catalog_queries -.->|"reads snapshot"| node_postgres
node_history_queries -->|"reads history"| node_postgres
node_shopper -.->|"opens catalog"| node_home
node_home -->|"renders"| node_latest
node_latest -->|"renders"| node_catalog_explorer
node_catalog_explorer -->|"renders"| node_filters
node_catalog_explorer -->|"renders"| node_product_card
node_catalog_explorer -->|"uses"| node_catalog_hook
node_filters -->|"updates filters"| node_catalog_hook
node_catalog_hook -->|"fetches pages"| node_catalog_api
node_catalog_api -->|"calls"| node_catalog_service
node_catalog_service -->|"queries products"| node_catalog_queries
node_product_card -->|"renders"| node_swatches
node_product_card -->|"renders"| node_sizes
node_shopper -.->|"opens product"| node_product_page
node_product_page -->|"renders"| node_history_explorer
node_history_explorer -.->|"loads history"| node_history_api
node_history_api -->|"queries prices"| node_history_queries
node_history_api -->|"formats rows"| node_history_service
node_history_api -->|"builds chart data"| node_chart_service
node_date_api -->|"queries date"| node_history_queries
node_date_api -->|"formats rows"| node_history_service
node_chart_service -->|"uses history types"| node_history_service
node_history_explorer -->|"renders"| node_price_chart
node_history_explorer -->|"renders"| node_availability_chart
node_view_generator -->|"reads JSONL output"| node_details

click node_scraper "https://github.com/keejung7/aritziapricetracker/blob/main/scraper.js"
click node_details "https://github.com/keejung7/aritziapricetracker/blob/main/details_scraper.js"
click node_loader "https://github.com/keejung7/aritziapricetracker/blob/main/db/db.js"
click node_parser "https://github.com/keejung7/aritziapricetracker/blob/main/db/parser.js"
click node_catalog_refresh "https://github.com/keejung7/aritziapricetracker/blob/main/db/catalogReadModel.js"
click node_refresh_command "https://github.com/keejung7/aritziapricetracker/blob/main/db/refresh_catalog_read_model.js"
click node_catalog_queries "https://github.com/keejung7/aritziapricetracker/blob/main/db/catalogQueries.js"
click node_history_queries "https://github.com/keejung7/aritziapricetracker/blob/main/db/queries.js"
click node_home "https://github.com/keejung7/aritziapricetracker/blob/main/app/page.tsx"
click node_latest "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/LatestProductsExplorer.tsx"
click node_catalog_explorer "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/CatalogExplorer.tsx"
click node_filters "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/CatalogFilters.tsx"
click node_catalog_hook "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/useCatalogProducts.ts"
click node_catalog_api "https://github.com/keejung7/aritziapricetracker/blob/main/app/api/catalog/products/route.ts"
click node_catalog_service "https://github.com/keejung7/aritziapricetracker/blob/main/app/services/catalogService.ts"
click node_product_card "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/ProductCard.tsx"
click node_swatches "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/ColorSwatches.tsx"
click node_sizes "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/AvailableSizes.tsx"
click node_product_page "https://github.com/keejung7/aritziapricetracker/blob/main/app/products/%5BproductNo%5D/page.tsx"
click node_history_explorer "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/ProductPriceHistoryExplorer.tsx"
click node_history_api "https://github.com/keejung7/aritziapricetracker/blob/main/app/api/products/%5BproductNo%5D/price-history/route.ts"
click node_date_api "https://github.com/keejung7/aritziapricetracker/blob/main/app/api/products/%5BproductNo%5D/prices/%5Bdate%5D/route.ts"
click node_history_service "https://github.com/keejung7/aritziapricetracker/blob/main/app/services/priceHistoryService.ts"
click node_chart_service "https://github.com/keejung7/aritziapricetracker/blob/main/app/services/productChartService.ts"
click node_price_chart "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/product/PriceHistoryChart.tsx"
click node_availability_chart "https://github.com/keejung7/aritziapricetracker/blob/main/app/components/product/AvailabilityHistoryChart.tsx"
click node_view_generator "https://github.com/keejung7/aritziapricetracker/blob/main/generate_view.js"

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_scraper,node_details,node_view_generator toneBlue
class node_loader,node_parser,node_catalog_refresh,node_refresh_command,node_postgres,node_catalog_queries,node_history_queries toneAmber
class node_home,node_latest,node_catalog_explorer,node_filters,node_catalog_hook,node_catalog_api,node_catalog_service,node_product_card,node_swatches,node_sizes toneMint
class node_product_page,node_history_explorer,node_history_api,node_date_api,node_history_service,node_chart_service,node_price_chart,node_availability_chart toneRose
class node_aritzia,node_shopper toneIndigo
```

## Components

### Data collection

- [URL scraper](https://github.com/keejung7/aritziapricetracker/blob/main/scraper.js): `scraper.js`
- [Detail scraper](https://github.com/keejung7/aritziapricetracker/blob/main/details_scraper.js): `details_scraper.js`
- [HTML data view](https://github.com/keejung7/aritziapricetracker/blob/main/generate_view.js): `generate_view.js`

### Database and catalog

- [Raw data loader](https://github.com/keejung7/aritziapricetracker/blob/main/db/db.js): `db/db.js`
- [Artifact parser](https://github.com/keejung7/aritziapricetracker/blob/main/db/parser.js): `db/parser.js`
- [Catalog refresh](https://github.com/keejung7/aritziapricetracker/blob/main/db/catalogReadModel.js): `db/catalogReadModel.js`
- [Refresh command](https://github.com/keejung7/aritziapricetracker/blob/main/db/refresh_catalog_read_model.js): `db/refresh_catalog_read_model.js`
- **PostgreSQL**
- [Catalog queries](https://github.com/keejung7/aritziapricetracker/blob/main/db/catalogQueries.js): `db/catalogQueries.js`
- [History queries](https://github.com/keejung7/aritziapricetracker/blob/main/db/queries.js): `db/queries.js`

### Catalog browsing

- [Catalog page](https://github.com/keejung7/aritziapricetracker/blob/main/app/page.tsx): `app/page.tsx`
- [Catalog entry](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/LatestProductsExplorer.tsx): `app/components/LatestProductsExplorer.tsx`
- [Catalog explorer](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/CatalogExplorer.tsx): `app/components/catalog/CatalogExplorer.tsx`
- [Catalog filters](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/CatalogFilters.tsx): `app/components/catalog/CatalogFilters.tsx`
- [Catalog data hook](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/useCatalogProducts.ts): `app/components/catalog/useCatalogProducts.ts`
- [Catalog API](https://github.com/keejung7/aritziapricetracker/blob/main/app/api/catalog/products/route.ts): `app/api/catalog/products/route.ts`
- [Catalog service](https://github.com/keejung7/aritziapricetracker/blob/main/app/services/catalogService.ts): `app/services/catalogService.ts`
- [Product cards](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/ProductCard.tsx): `app/components/catalog/ProductCard.tsx`
- [Color swatches](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/ColorSwatches.tsx): `app/components/catalog/ColorSwatches.tsx`
- [Available sizes](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/catalog/AvailableSizes.tsx): `app/components/catalog/AvailableSizes.tsx`

### Product history

- [Product page](https://github.com/keejung7/aritziapricetracker/blob/main/app/products/%5BproductNo%5D/page.tsx): `app/products/[productNo]/page.tsx`
- [History explorer](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/ProductPriceHistoryExplorer.tsx): `app/components/ProductPriceHistoryExplorer.tsx`
- [History API](https://github.com/keejung7/aritziapricetracker/blob/main/app/api/products/%5BproductNo%5D/price-history/route.ts): `app/api/products/[productNo]/price-history/route.ts`
- [Date price API](https://github.com/keejung7/aritziapricetracker/blob/main/app/api/products/%5BproductNo%5D/prices/%5Bdate%5D/route.ts): `app/api/products/[productNo]/prices/[date]/route.ts`
- [History formatter](https://github.com/keejung7/aritziapricetracker/blob/main/app/services/priceHistoryService.ts): `app/services/priceHistoryService.ts`
- [Chart history logic](https://github.com/keejung7/aritziapricetracker/blob/main/app/services/productChartService.ts): `app/services/productChartService.ts`
- [Price chart](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/product/PriceHistoryChart.tsx): `app/components/product/PriceHistoryChart.tsx`
- [Availability chart](https://github.com/keejung7/aritziapricetracker/blob/main/app/components/product/AvailabilityHistoryChart.tsx): `app/components/product/AvailabilityHistoryChart.tsx`

### Other components

- **Aritzia site**
- **Shopper**

## Connections

- URL scraper → Aritzia site: scrapes categories
- Detail scraper → Aritzia site: scrapes products
- URL scraper → Detail scraper: provides product links
- Detail scraper → Raw data loader: provides JSONL
- Raw data loader → Artifact parser: parses input (evidence: `db/db.js`)
- Raw data loader → PostgreSQL: upserts observations
- Raw data loader → Catalog refresh: refreshes catalog (evidence: `db/db.js`)
- Refresh command → Catalog refresh: runs refresh (evidence: `db/refresh_catalog_read_model.js`)
- Catalog refresh → PostgreSQL: builds snapshots
- Catalog queries → PostgreSQL: reads snapshot
- History queries → PostgreSQL: reads history
- Shopper → Catalog page: opens catalog
- Catalog page → Catalog entry: renders (evidence: `app/page.tsx`)
- Catalog entry → Catalog explorer: renders (evidence: `app/components/LatestProductsExplorer.tsx`)
- Catalog explorer → Catalog filters: renders (evidence: `app/components/catalog/CatalogExplorer.tsx`)
- Catalog explorer → Product cards: renders (evidence: `app/components/catalog/CatalogExplorer.tsx`)
- Catalog explorer → Catalog data hook: uses (evidence: `app/components/catalog/CatalogExplorer.tsx`)
- Catalog filters → Catalog data hook: updates filters (evidence: `app/components/catalog/CatalogFilters.tsx`)
- Catalog data hook → Catalog API: fetches pages (evidence: `app/components/catalog/useCatalogProducts.ts`)
- Catalog API → Catalog service: calls (evidence: `app/api/catalog/products/route.ts`)
- Catalog service → Catalog queries: queries products (evidence: `app/services/catalogService.ts`)
- Product cards → Color swatches: renders (evidence: `app/components/catalog/ProductCard.tsx`)
- Product cards → Available sizes: renders (evidence: `app/components/catalog/ProductCard.tsx`)
- Shopper → Product page: opens product
- Product page → History explorer: renders (evidence: `app/products/[productNo]/page.tsx`)
- History explorer → History API: loads history
- History API → History queries: queries prices (evidence: `app/api/products/[productNo]/price-history/route.ts`)
- History API → History formatter: formats rows (evidence: `app/api/products/[productNo]/price-history/route.ts`)
- History API → Chart history logic: builds chart data (evidence: `app/api/products/[productNo]/price-history/route.ts`)
- Date price API → History queries: queries date (evidence: `app/api/products/[productNo]/prices/[date]/route.ts`)
- Date price API → History formatter: formats rows (evidence: `app/api/products/[productNo]/prices/[date]/route.ts`)
- Chart history logic → History formatter: uses history types (evidence: `app/services/productChartService.ts`)
- History explorer → Price chart: renders (evidence: `app/components/ProductPriceHistoryExplorer.tsx`)
- History explorer → Availability chart: renders (evidence: `app/components/ProductPriceHistoryExplorer.tsx`)
- HTML data view → Detail scraper: reads JSONL output
