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.
|
Saturated fat, sugars, salt, calories, trans fat, additives, prep method, controversies, and ingredient concerns — weighted and combined into a single 1–100 score. |
2,995 canonical ingredients with EFSA concern tiers, additive classification, palm oil detection, and vegan/vegetarian flags. |
Every product has a 0–100 confidence score showing data completeness — so you know how much to trust each number. |
EAN-13 barcode lookup with 99.8% coverage. Scan any product to see its full scoring breakdown instantly. |
| 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 |
|
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┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────────┐
│ 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.
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).
| 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 |
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
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):
- PR Gate — Typecheck → Lint → Build → Unit tests → Playwright smoke E2E
- Main Gate — Above + Coverage → SonarCloud Quality Gate
- QA Gate — Schema → Pipelines → 733 QA checks → Sanity → Confidence threshold
- Nightly — Full Playwright (all projects) + Data Integrity Audit
Contributions are welcome! Please follow the project conventions:
- Branch naming:
feat/,fix/,docs/,chore/,schema/,data/ - Commit messages: Conventional Commits — enforced on PR titles
- Testing: Every change must include tests. See copilot-instructions.md §8
- Migrations: Append-only. Never modify existing
supabase/migrations/files - QA:
.\RUN_QA.ps1must pass (733/733) before merging
Core
- SCORING_METHODOLOGY.md — v3.2 algorithm (9 factors, ceilings, bands)
- API_CONTRACTS.md — API surface contracts and response shapes
- API_CONVENTIONS.md — RPC naming, breaking changes, security standards
- ARCHITECTURE.md — System architecture overview
- DATA_SOURCES.md — Multi-source data hierarchy & validation
- RESEARCH_WORKFLOW.md — Data collection lifecycle
- FRONTEND_API_MAP.md — Frontend ↔ API mapping
- SCORING_ENGINE.md — Scoring engine architecture & versioning
Operations
- VIEWING_AND_TESTING.md — Queries, Studio UI, test runner
- DEPLOYMENT.md — Deployment procedures & rollback playbook
- ENVIRONMENT_STRATEGY.md — Local / Staging / Production
- COUNTRY_EXPANSION_GUIDE.md — Multi-country protocol
- MIGRATION_CONVENTIONS.md — Migration safety & idempotency
- BACKFILL_STANDARD.md — Backfill orchestration
- EAN_VALIDATION_STATUS.md — EAN coverage (99.8%)
Quality & Security
- SECURITY.md — Security policy & threat model
- SECURITY_AUDIT.md — Full security audit report
- DATA_INTEGRITY_AUDITS.md — Data integrity framework
- PRIVACY_CHECKLIST.md — GDPR/RODO compliance
- PERFORMANCE_REPORT.md — Performance audit & projections
- SLO.md — Service Level Objectives
- RATE_LIMITING.md — Rate limiting & abuse prevention
Governance & CI
- GOVERNANCE_BLUEPRINT.md — Execution governance plan
- CI_ARCHITECTURE_PROPOSAL.md — CI pipeline design
- CONTRACT_TESTING.md — API contract testing strategy
- DRIFT_DETECTION.md — 8-check drift detection catalog
- INCIDENT_RESPONSE.md — Incident playbook
- MONITORING.md — Runtime monitoring
- OBSERVABILITY.md — Observability strategy
- SONAR.md — SonarCloud configuration
Design & UX
- UX_UI_DESIGN.md — Production-ready UX spec
- UX_IMPACT_METRICS.md — UX measurement standard
- BRAND_GUIDELINES.md — Visual identity reference
- SEARCH_ARCHITECTURE.md — pg_trgm + tsvector search
📄 Full index: docs/INDEX.md
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
