# jeightz/test architecture

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

- Interactive diagram: https://gitdiagram.com/jeightz/test
- Repository: https://github.com/jeightz/test

## Overview

Priceter is a login-free, crowdsourced local-price verification app. Consumers search by text or image, inspect a product’s community reports and DTI SRP, then submit a price report or rate another report; receipt scanning offers an alternate submission path. Product-detail computation compares reports with SRP and local medians and summarizes trust. The graph preserves the documented nearby-price, trust, and daily-limit capabilities. Some UI-to-API links are dashed because sampled excerpts do not show those requests; unsampled routes are represented by their exact tree paths.

Main entry points: [`app/api/receipts/analyze/route.js`](https://github.com/jeightz/test/blob/main/app/api/receipts/analyze/route.js) (Receipt analysis), [`app/api/reports/route.js`](https://github.com/jeightz/test/blob/main/app/api/reports/route.js) (Price reporting), [`app/product/[id]/page.js`](https://github.com/jeightz/test/blob/main/app/product/%5Bid%5D/page.js) (Product details), [`app/api/products/[id]/route.js`](https://github.com/jeightz/test/blob/main/app/api/products/%5Bid%5D/route.js) (Price analysis)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_experience["Consumer experience"]
  node_search_page["Search page<br/>[page.js]"]
  node_search_bar["Search controls<br/>[SearchBar.jsx]"]
  node_camera_search["Camera search<br/>[CameraSearch.jsx]"]
  node_search_api["Image matching<br/>[route.js]"]
  node_products_api["Product search<br/>[route.js]"]
  node_product_grid["Product results<br/>[ProductGrid.jsx]"]
  node_product_page["Product details<br/>[page.js]"]
  node_product_api["Price analysis<br/>[route.js]"]
  node_price_indicator["Price indicator<br/>[PriceIndicator.jsx]"]
  node_local_median["Local median<br/>[LocalMedian.jsx]"]
  node_trust_score["Trust summary<br/>[TrustScore.jsx]"]
end

subgraph group_reporting["Reporting and trust"]
  node_receipt_page["Receipt upload<br/>[page.js]"]
  node_receipt_ui["Receipt workflow<br/>[ReceiptUpload.jsx]"]
  node_receipt_analyze["Receipt analysis<br/>[route.js]"]
  node_receipt_submit["Receipt submission<br/>[route.js]"]
  node_report_api["Price reporting<br/>[route.js]"]
  node_rating_api["Report rating<br/>[route.js]"]
  node_report_list["Recent reports<br/>[ReportList.jsx]"]
  node_location_picker["Location picker<br/>[LocationPicker.jsx]"]
end

subgraph group_services["Domain services"]
  node_session_api["Session endpoint<br/>[route.js]"]
  node_session["Anonymous session<br/>[session.js]"]
  node_limits["Daily limits<br/>[limits.js]"]
  node_price_logic["Price calculations<br/>[price.js]"]
  node_location_logic["Nearby distances<br/>[location.js]"]
  node_location_fields["Location fields<br/>[locationFields.js]"]
  node_trust_logic["Trust calculations<br/>[trust.js]"]
  node_report_helpers["Report helpers<br/>[reportHelpers.js]"]
  node_embedding["Image embeddings<br/>[embedding.js]"]
  node_gemini["Receipt extraction<br/>[gemini.js]"]
  node_cloudinary["Image hosting<br/>[cloudinary.js]"]
  node_image_helpers["Product images<br/>[productImages.js]"]
end

subgraph group_storage["Persistence"]
  node_database[("PostgreSQL<br/>[db.js]")]
end

node_consumer(("Consumer"))
node_jina["Jina embeddings"]

node_consumer -->|"searches"| node_search_page
node_search_page -->|"renders"| node_search_bar
node_search_page -->|"renders"| node_product_grid
node_search_bar -->|"renders"| node_camera_search
node_search_bar -->|"posts image"| node_search_api
node_search_page -.->|"requests results"| node_products_api
node_product_grid -->|"renders"| node_price_indicator
node_product_page -.->|"loads details"| node_product_api
node_product_api -->|"queries"| node_database
node_product_api -->|"classifies prices"| node_price_logic
node_product_api -->|"builds nearby query"| node_location_logic
node_product_api -->|"gets session"| node_session
node_product_api -->|"builds distribution"| node_trust_logic
node_product_page -->|"renders"| node_price_indicator
node_product_page -->|"renders"| node_local_median
node_product_page -->|"renders"| node_report_list
node_product_page -->|"renders"| node_trust_score
node_product_page -->|"formats product image"| node_image_helpers
node_consumer -->|"uploads receipt"| node_receipt_page
node_receipt_page -->|"renders"| node_receipt_ui
node_receipt_ui -->|"uses"| node_location_picker
node_receipt_ui -.->|"submits for analysis"| node_receipt_analyze
node_receipt_ui -.->|"submits reports"| node_receipt_submit
node_receipt_analyze -->|"extracts products"| node_gemini
node_receipt_analyze -->|"matches products"| node_report_helpers
node_receipt_analyze -->|"uploads receipt"| node_cloudinary
node_receipt_analyze -->|"gets session"| node_session
node_receipt_analyze -->|"checks scan limit"| node_limits
node_receipt_analyze -->|"reads matches"| node_database
node_consumer -.->|"reports price"| node_report_api
node_report_api -->|"gets session"| node_session
node_report_api -->|"checks report limit"| node_limits
node_report_api -->|"embeds photo"| node_embedding
node_report_api -->|"inserts report"| node_report_helpers
node_report_api -->|"uploads photo"| node_cloudinary
node_report_api -->|"opens transaction"| node_database
node_consumer -.->|"rates report"| node_rating_api
node_rating_api -->|"gets session"| node_session
node_rating_api -->|"checks rating limit"| node_limits
node_rating_api -->|"saves rating"| node_database
node_report_list -->|"renders"| node_price_indicator
node_report_list -->|"renders"| node_trust_score
node_session_api -->|"gets session"| node_session
node_session -->|"reads and writes"| node_database
node_limits -->|"counts and logs"| node_database
node_report_helpers -->|"uses vector helper"| node_embedding
node_embedding -->|"requests vectors"| node_jina
node_location_picker -->|"uses location fields"| node_location_fields

click node_search_page "https://github.com/jeightz/test/blob/main/app/search/page.js"
click node_search_bar "https://github.com/jeightz/test/blob/main/components/SearchBar.jsx"
click node_camera_search "https://github.com/jeightz/test/blob/main/components/CameraSearch.jsx"
click node_search_api "https://github.com/jeightz/test/blob/main/app/api/search-by-image/route.js"
click node_products_api "https://github.com/jeightz/test/blob/main/app/api/products/route.js"
click node_product_grid "https://github.com/jeightz/test/blob/main/components/ProductGrid.jsx"
click node_product_page "https://github.com/jeightz/test/blob/main/app/product/%5Bid%5D/page.js"
click node_product_api "https://github.com/jeightz/test/blob/main/app/api/products/%5Bid%5D/route.js"
click node_price_indicator "https://github.com/jeightz/test/blob/main/components/PriceIndicator.jsx"
click node_local_median "https://github.com/jeightz/test/blob/main/components/LocalMedian.jsx"
click node_trust_score "https://github.com/jeightz/test/blob/main/components/TrustScore.jsx"
click node_receipt_page "https://github.com/jeightz/test/blob/main/app/receipt-upload/page.js"
click node_receipt_ui "https://github.com/jeightz/test/blob/main/components/ReceiptUpload.jsx"
click node_receipt_analyze "https://github.com/jeightz/test/blob/main/app/api/receipts/analyze/route.js"
click node_receipt_submit "https://github.com/jeightz/test/blob/main/app/api/receipts/submit/route.js"
click node_report_api "https://github.com/jeightz/test/blob/main/app/api/reports/route.js"
click node_rating_api "https://github.com/jeightz/test/blob/main/app/api/ratings/route.js"
click node_report_list "https://github.com/jeightz/test/blob/main/components/ReportList.jsx"
click node_session_api "https://github.com/jeightz/test/blob/main/app/api/session/route.js"
click node_session "https://github.com/jeightz/test/blob/main/lib/session.js"
click node_limits "https://github.com/jeightz/test/blob/main/lib/limits.js"
click node_price_logic "https://github.com/jeightz/test/blob/main/lib/price.js"
click node_location_logic "https://github.com/jeightz/test/blob/main/lib/location.js"
click node_location_fields "https://github.com/jeightz/test/blob/main/lib/locationFields.js"
click node_trust_logic "https://github.com/jeightz/test/blob/main/lib/trust.js"
click node_report_helpers "https://github.com/jeightz/test/blob/main/lib/reportHelpers.js"
click node_embedding "https://github.com/jeightz/test/blob/main/lib/embedding.js"
click node_gemini "https://github.com/jeightz/test/blob/main/lib/gemini.js"
click node_cloudinary "https://github.com/jeightz/test/blob/main/lib/cloudinary.js"
click node_image_helpers "https://github.com/jeightz/test/blob/main/lib/productImages.js"
click node_location_picker "https://github.com/jeightz/test/blob/main/components/LocationPicker.jsx"
click node_database "https://github.com/jeightz/test/blob/main/lib/db.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_search_page,node_search_bar,node_camera_search,node_search_api,node_products_api,node_product_grid,node_product_page,node_product_api,node_price_indicator,node_local_median,node_trust_score toneBlue
class node_receipt_page,node_receipt_ui,node_receipt_analyze,node_receipt_submit,node_report_api,node_rating_api,node_report_list,node_location_picker toneAmber
class node_session_api,node_session,node_limits,node_price_logic,node_location_logic,node_location_fields,node_trust_logic,node_report_helpers,node_embedding,node_gemini,node_cloudinary,node_image_helpers toneMint
class node_database toneRose
class node_consumer,node_jina toneIndigo
```

## Components

### Consumer experience

- [Search page](https://github.com/jeightz/test/blob/main/app/search/page.js): `app/search/page.js`
- [Search controls](https://github.com/jeightz/test/blob/main/components/SearchBar.jsx): `components/SearchBar.jsx`
- [Camera search](https://github.com/jeightz/test/blob/main/components/CameraSearch.jsx): `components/CameraSearch.jsx`
- [Image matching](https://github.com/jeightz/test/blob/main/app/api/search-by-image/route.js): `app/api/search-by-image/route.js`
- [Product search](https://github.com/jeightz/test/blob/main/app/api/products/route.js): `app/api/products/route.js`
- [Product results](https://github.com/jeightz/test/blob/main/components/ProductGrid.jsx): `components/ProductGrid.jsx`
- [Product details](https://github.com/jeightz/test/blob/main/app/product/%5Bid%5D/page.js): `app/product/[id]/page.js`
- [Price analysis](https://github.com/jeightz/test/blob/main/app/api/products/%5Bid%5D/route.js): `app/api/products/[id]/route.js`
- [Price indicator](https://github.com/jeightz/test/blob/main/components/PriceIndicator.jsx): `components/PriceIndicator.jsx`
- [Local median](https://github.com/jeightz/test/blob/main/components/LocalMedian.jsx): `components/LocalMedian.jsx`
- [Trust summary](https://github.com/jeightz/test/blob/main/components/TrustScore.jsx): `components/TrustScore.jsx`

### Reporting and trust

- [Receipt upload](https://github.com/jeightz/test/blob/main/app/receipt-upload/page.js): `app/receipt-upload/page.js`
- [Receipt workflow](https://github.com/jeightz/test/blob/main/components/ReceiptUpload.jsx): `components/ReceiptUpload.jsx`
- [Receipt analysis](https://github.com/jeightz/test/blob/main/app/api/receipts/analyze/route.js): `app/api/receipts/analyze/route.js`
- [Receipt submission](https://github.com/jeightz/test/blob/main/app/api/receipts/submit/route.js): `app/api/receipts/submit/route.js`
- [Price reporting](https://github.com/jeightz/test/blob/main/app/api/reports/route.js): `app/api/reports/route.js`
- [Report rating](https://github.com/jeightz/test/blob/main/app/api/ratings/route.js): `app/api/ratings/route.js`
- [Recent reports](https://github.com/jeightz/test/blob/main/components/ReportList.jsx): `components/ReportList.jsx`
- [Location picker](https://github.com/jeightz/test/blob/main/components/LocationPicker.jsx): `components/LocationPicker.jsx`

### Domain services

- [Session endpoint](https://github.com/jeightz/test/blob/main/app/api/session/route.js): `app/api/session/route.js`
- [Anonymous session](https://github.com/jeightz/test/blob/main/lib/session.js): `lib/session.js`
- [Daily limits](https://github.com/jeightz/test/blob/main/lib/limits.js): `lib/limits.js`
- [Price calculations](https://github.com/jeightz/test/blob/main/lib/price.js): `lib/price.js`
- [Nearby distances](https://github.com/jeightz/test/blob/main/lib/location.js): `lib/location.js`
- [Location fields](https://github.com/jeightz/test/blob/main/lib/locationFields.js): `lib/locationFields.js`
- [Trust calculations](https://github.com/jeightz/test/blob/main/lib/trust.js): `lib/trust.js`
- [Report helpers](https://github.com/jeightz/test/blob/main/lib/reportHelpers.js): `lib/reportHelpers.js`
- [Image embeddings](https://github.com/jeightz/test/blob/main/lib/embedding.js): `lib/embedding.js`
- [Receipt extraction](https://github.com/jeightz/test/blob/main/lib/gemini.js): `lib/gemini.js`
- [Image hosting](https://github.com/jeightz/test/blob/main/lib/cloudinary.js): `lib/cloudinary.js`
- [Product images](https://github.com/jeightz/test/blob/main/lib/productImages.js): `lib/productImages.js`

### Persistence

- [PostgreSQL](https://github.com/jeightz/test/blob/main/lib/db.js): `lib/db.js`

### Other components

- **Consumer**
- **Jina embeddings**

## Connections

- Consumer → Search page: searches (evidence: `app/search/page.js`)
- Search page → Search controls: renders (evidence: `app/search/page.js`)
- Search page → Product results: renders (evidence: `app/search/page.js`)
- Search controls → Camera search: renders (evidence: `components/SearchBar.jsx`)
- Search controls → Image matching: posts image (evidence: `components/SearchBar.jsx`)
- Search page → Product search: requests results
- Product results → Price indicator: renders (evidence: `components/ProductGrid.jsx`)
- Product details → Price analysis: loads details
- Price analysis → PostgreSQL: queries (evidence: `app/api/products/[id]/route.js`)
- Price analysis → Price calculations: classifies prices (evidence: `app/api/products/[id]/route.js`)
- Price analysis → Nearby distances: builds nearby query (evidence: `app/api/products/[id]/route.js`)
- Price analysis → Anonymous session: gets session (evidence: `app/api/products/[id]/route.js`)
- Price analysis → Trust calculations: builds distribution (evidence: `app/api/products/[id]/route.js`)
- Product details → Price indicator: renders (evidence: `app/product/[id]/page.js`)
- Product details → Local median: renders (evidence: `app/product/[id]/page.js`)
- Product details → Recent reports: renders (evidence: `app/product/[id]/page.js`)
- Product details → Trust summary: renders (evidence: `app/product/[id]/page.js`)
- Product details → Product images: formats product image (evidence: `app/product/[id]/page.js`)
- Consumer → Receipt upload: uploads receipt (evidence: `app/receipt-upload/page.js`)
- Receipt upload → Receipt workflow: renders (evidence: `app/receipt-upload/page.js`)
- Receipt workflow → Location picker: uses (evidence: `components/ReceiptUpload.jsx`)
- Receipt workflow → Receipt analysis: submits for analysis
- Receipt workflow → Receipt submission: submits reports
- Receipt analysis → Receipt extraction: extracts products (evidence: `app/api/receipts/analyze/route.js`)
- Receipt analysis → Report helpers: matches products (evidence: `app/api/receipts/analyze/route.js`)
- Receipt analysis → Image hosting: uploads receipt (evidence: `app/api/receipts/analyze/route.js`)
- Receipt analysis → Anonymous session: gets session (evidence: `app/api/receipts/analyze/route.js`)
- Receipt analysis → Daily limits: checks scan limit (evidence: `app/api/receipts/analyze/route.js`)
- Receipt analysis → PostgreSQL: reads matches (evidence: `app/api/receipts/analyze/route.js`)
- Consumer → Price reporting: reports price
- Price reporting → Anonymous session: gets session (evidence: `app/api/reports/route.js`)
- Price reporting → Daily limits: checks report limit (evidence: `app/api/reports/route.js`)
- Price reporting → Image embeddings: embeds photo (evidence: `app/api/reports/route.js`)
- Price reporting → Report helpers: inserts report (evidence: `app/api/reports/route.js`)
- Price reporting → Image hosting: uploads photo (evidence: `app/api/reports/route.js`)
- Price reporting → PostgreSQL: opens transaction (evidence: `app/api/reports/route.js`)
- Consumer → Report rating: rates report
- Report rating → Anonymous session: gets session (evidence: `app/api/ratings/route.js`)
- Report rating → Daily limits: checks rating limit (evidence: `app/api/ratings/route.js`)
- Report rating → PostgreSQL: saves rating (evidence: `app/api/ratings/route.js`)
- Recent reports → Price indicator: renders (evidence: `components/ReportList.jsx`)
- Recent reports → Trust summary: renders (evidence: `components/ReportList.jsx`)
- Session endpoint → Anonymous session: gets session (evidence: `app/api/session/route.js`)
- Anonymous session → PostgreSQL: reads and writes (evidence: `lib/session.js`)
- Daily limits → PostgreSQL: counts and logs (evidence: `lib/limits.js`)
- Report helpers → Image embeddings: uses vector helper (evidence: `lib/reportHelpers.js`)
- Image embeddings → Jina embeddings: requests vectors (evidence: `lib/embedding.js`)
- Location picker → Location fields: uses location fields (evidence: `components/LocationPicker.jsx`)
