Skip to content

ericsocrat/tryvit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

621 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TryVit — Food Health Scanner

Build Status QA Checks Coverage Products Market Scoring Version License TypeScript PostgreSQL

Scan, score & compare food products with multi-axis health scoring.
Every product scored on 9 independent factors. Every number traceable to its source.
Not a calorie counter. Not a Nutri-Score app. A research-grade scoring engine.


✨ Feature Highlights

🧬 9-Factor Scoring

Saturated fat, sugars, salt, calories, trans fat, additives, prep method, controversies, and ingredient concerns — weighted and combined into a single 1–100 score.

🔬 Ingredient Intelligence

2,995 canonical ingredients with EFSA concern tiers, additive classification, palm oil detection, and vegan/vegetarian flags.

📊 Data Confidence

Every product has a 0–100 confidence score showing data completeness — so you know how much to trust each number.

📱 Barcode Scanner

EAN-13 barcode lookup with 99.8% coverage. Scan any product to see its full scoring breakdown instantly.


🔍 How It Differs

Dimension Nutri-Score Apps TryVit
Scoring axes 1 (A–E letter) 4 independent (unhealthiness, Nutri-Score, NOVA, confidence)
Additive analysis ✅ EFSA concern tiers + additive count
Processing level ✅ NOVA 1–4 integrated
Trans fat tracking ✅ Separate weighted factor
Controversy tracking ✅ Palm oil, artificial sweeteners
Data quality visibility Hidden ✅ Confidence score per product
Score explainability None ✅ Full factor breakdown with context
Source provenance Opaque ✅ Every product linked to source
Multi-country Varies ✅ PL primary + DE micro-pilot

🚀 Quick Start

1. Clone & Start DB

git clone https://github.com/ericsocrat/tryvit.git
cd tryvit
supabase start

2. Run Pipelines

# All categories + QA
.\RUN_LOCAL.ps1 -RunQA

# Single category
.\RUN_LOCAL.ps1 -Category chips

3. Start Frontend

cd frontend
npm ci
npm run dev
# → http://localhost:3000
📋 Full Command Reference
# ── Database ──
supabase start                           # Start local Supabase
supabase db reset                        # Full rebuild (migrations + seed)

# ── Pipelines ──
.\RUN_LOCAL.ps1 -RunQA                   # All categories + QA validation
.\RUN_LOCAL.ps1 -Category dairy          # Single category
.\RUN_SEED.ps1                           # Seed reference data only

# ── Testing ──
.\RUN_QA.ps1                             # 733 QA checks across 48 suites
.\RUN_NEGATIVE_TESTS.ps1                 # 23 constraint violation tests
.\RUN_SANITY.ps1 -Env local              # Row-count + schema assertions
python validate_eans.py                  # EAN checksum validation
python check_pipeline_structure.py       # Pipeline folder/file structure

# ── Frontend ──
cd frontend
npm run dev                              # Dev server (localhost:3000)
npm run build                            # Production build
npx tsc --noEmit                         # TypeScript check
npm run lint                             # ESLint
npx vitest run                           # Unit tests (Vitest)
npm run test:coverage                    # Unit tests + v8 coverage
npx playwright test                      # E2E smoke tests (Playwright)

# ── Data Access ──
echo "SELECT * FROM v_master LIMIT 5;" | docker exec -i supabase_db_tryvit psql -U postgres -d postgres

🏗️ Architecture

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────────────┐
│  Open Food Facts │────▶│  Python Pipeline │────▶│  PostgreSQL (Supabase)  │
│  API v2          │     │  sql_generator   │     │  185 migrations         │
│  (category tags, │     │  validator       │     │  25 pipeline folders    │
│   countries=PL)  │     │  off_client      │     │  products + nutrition   │
└─────────────────┘     └──────────────────┘     │  + ingredients + scores │
                                                  └───────────┬─────────────┘
                                                              │
                                                  ┌───────────▼─────────────┐
                                                  │  API Layer              │
                                                  │  30+ RPC functions      │
                                                  │  RLS + SECURITY DEFINER │
                                                  │  pg_trgm search         │
                                                  └───────────┬─────────────┘
                                                              │
                                                  ┌───────────▼─────────────┐
                                                  │  Next.js 15 Frontend    │
                                                  │  App Router + SSR       │
                                                  │  TanStack Query v5      │
                                                  │  Supabase Auth          │
                                                  └─────────────────────────┘

Data flow: OFF API → Python pipeline generates idempotent SQL → PostgreSQL stores products, nutrition, ingredients, allergens → Scoring function compute_unhealthiness_v32() computes scores → API functions expose structured JSONB → Next.js frontend renders.


📈 Scoring Engine (v3.2)

unhealthiness_score (1–100) =
  sat_fat(0.17) + sugars(0.17) + salt(0.17) + calories(0.10) +
  trans_fat(0.11) + additives(0.07) + prep_method(0.08) +
  controversies(0.08) + ingredient_concern(0.05)
🟢 1–20
Low risk
🟡 21–40
Moderate
🟠 41–60
Elevated
🔴 61–80
High risk
⬛ 81–100
Very high

Ceilings (per 100 g): sat fat 10 g · sugars 27 g · salt 3 g · trans fat 2 g · calories 600 kcal · additives 10

Every score is fully explainable via api_score_explanation() — returns the 9 factors with raw values, weights, and category context (rank, average, percentile).

📄 Full methodology →


📊 By the Numbers

1,281
Active Products
25
Categories
PL
Primary Market
2,995
Ingredients
99.8%
EAN Coverage
182
Migrations
733
QA Checks
48
Test Suites
23
Negative Tests
≥88%
Line Coverage
30+
API Functions
v3.2
Scoring Engine

🛠️ Tech Stack

PostgreSQL Supabase Next.js TypeScript Tailwind CSS TanStack Query Python Playwright Vitest GitHub Actions SonarCloud Sentry


📁 Project Structure

Click to expand full directory tree
tryvit/
├── pipeline/                        # Python OFF API → SQL generator
│   ├── run.py                       # CLI: --category, --max-products, --dry-run, --country
│   ├── off_client.py                # OFF API v2 client with retry logic
│   ├── sql_generator.py             # Generates 4–5 SQL files per category
│   ├── validator.py                 # Data validation before SQL generation
│   ├── categories.py                # 25 category definitions + OFF tag mappings
│   └── image_importer.py            # Product image import utility
│
├── db/
│   ├── pipelines/                   # 25 category folders (20 PL + 5 DE)
│   │   ├── chips-pl/                # Reference PL implementation
│   │   ├── chips-de/                # Germany micro-pilot (51 products)
│   │   ├── bread-de/                # DE Bread
│   │   ├── dairy-de/                # DE Dairy
│   │   ├── drinks-de/               # DE Drinks
│   │   ├── sweets-de/               # DE Sweets
│   │   └── ... (19 more PL)         # Variable product counts per category
│   ├── qa/                          # 48 test suites (733 checks)
│   └── views/                       # Reference view definitions
│
├── supabase/
│   ├── migrations/                  # 185 append-only schema migrations
│   ├── seed/                        # Reference data seeds
│   ├── tests/                       # pgTAP integration tests
│   └── functions/                   # Edge Functions (API gateway, push notifications)
│
├── frontend/                        # Next.js 15 App Router
│   ├── src/
│   │   ├── app/                     # Pages (App Router)
│   │   ├── components/              # React components
│   │   ├── hooks/                   # TanStack Query hooks
│   │   ├── stores/                  # Zustand stores
│   │   └── lib/                     # API clients, types, utilities
│   ├── e2e/                         # Playwright E2E tests
│   └── messages/                    # i18n dictionaries (en, pl)
│
├── docs/                            # 45+ project documents
│   ├── SCORING_METHODOLOGY.md       # v3.2 algorithm specification
│   ├── API_CONTRACTS.md             # API surface contracts
│   ├── ARCHITECTURE.md              # System architecture overview
│   ├── decisions/                   # Architecture Decision Records (MADR 3.0)
│   └── assets/                      # Brand assets (logo, banners)
│
├── .github/workflows/               # 18 CI/CD workflows
├── scripts/                         # Utility & governance scripts
├── monitoring/                      # Alert definitions
│
├── RUN_LOCAL.ps1                    # Pipeline runner (idempotent)
├── RUN_QA.ps1                       # QA test runner (733 checks)
├── RUN_NEGATIVE_TESTS.ps1           # Negative test runner (23 tests)
├── RUN_SANITY.ps1                   # Sanity checks
├── CHANGELOG.md                     # Structured changelog
├── DEPLOYMENT.md                    # Deployment procedures & rollback
└── SECURITY.md                      # Security policy

🧪 Testing

Every change is validated against 733 automated checks across 48 QA suites plus 20 negative validation tests. No data enters the database without verification.

Layer Tool Checks Location
Database QA Raw SQL (zero rows = pass) 733 db/qa/QA__*.sql
Negative Tests SQL constraint validation 23 db/qa/TEST__*.sql
Unit Tests Vitest (jsdom, v8 coverage) frontend/src/**/*.test.{ts,tsx}
E2E Tests Playwright (Chromium) frontend/e2e/*.spec.ts
pgTAP PostgreSQL TAP testing supabase/tests/*.test.sql
EAN Validation GS1 checksum verifier 1 validate_eans.py
Code Quality SonarCloud CI (main-gate.yml)

CI Pipeline (GitHub Actions, tiered):

  1. PR Gate — Typecheck → Lint → Build → Unit tests → Playwright smoke E2E
  2. Main Gate — Above + Coverage → SonarCloud Quality Gate
  3. QA Gate — Schema → Pipelines → 733 QA checks → Sanity → Confidence threshold
  4. Nightly — Full Playwright (all projects) + Data Integrity Audit

🤝 Contributing

Contributions are welcome! Please follow the project conventions:

  1. Branch naming: feat/, fix/, docs/, chore/, schema/, data/
  2. Commit messages: Conventional Commits — enforced on PR titles
  3. Testing: Every change must include tests. See copilot-instructions.md §8
  4. Migrations: Append-only. Never modify existing supabase/migrations/ files
  5. QA: .\RUN_QA.ps1 must pass (733/733) before merging

📚 Documentation

Core
Operations
Quality & Security
Governance & CI
Design & UX

📄 Full index: docs/INDEX.md


📜 License

This project is licensed under the terms in the LICENSE file.

Data acknowledgments:

  • Open Food Facts — Product data source (ODbL license)
  • Supabase — Database platform
  • EFSA — Food additive concern tier classifications

TryVit
Built with science and care.