# NomNomVegan — Full LLM Reference

> Community-powered vegan barcode scanner for Android. Scan a product, get an instant verdict. Built by vegans, for vegans.

## What is NomNomVegan?

NomNomVegan is a free Android app that tells you instantly whether a food product is vegan. The verdict comes from a community-maintained database of verified products, backed by Open Food Facts as a fallback, with on-device OCR ingredient analysis as a last resort.

The app is live on Google Play and has active users across Europe. The company legal name is **NomNomVegan Oy**, registered in Finland.

---

## Core scan flow

1. User scans a product barcode
2. App checks the NomNomVegan community database first (authoritative)
3. Falls back to Open Food Facts for name/ingredients when community has no verdict
4. If product not found at all, user can photograph the ingredient list — on-device OCR analyses it in 13 languages
5. Verdicts: **vegan** / **not vegan** / **unknown**

---

## Verdict sources

| Source | Meaning |
|--------|---------|
| `community` | Verified by NomNomVegan contributors |
| `admin_override` | Manually set by NomNomVegan moderators — most authoritative |
| `off_tags` | Derived from Open Food Facts vegan tag |
| `ocr` | On-device ingredient analysis — high confidence but not community-verified |
| `uncertain` | Product found but vegan status unconfirmed |
| `not_found` | Product not in any database |

---

## Features

### Barcode scanning
- Instant lookup for any EAN/UPC barcode
- Results cached in Redis for 24 hours per barcode
- Returns full product data: name, brand, image, ingredients, verdict, confidence score, community stats

### OCR ingredient scanning
- Camera-based ingredient list analysis, fully on-device
- No network call, zero latency
- Supported languages: English, Finnish, Swedish, German, French, Spanish, Italian, Dutch, Norwegian, Danish, Estonian, Polish, Portuguese
- Matches against keyword lists for: dairy (milk, cheese, whey, casein, butter, cream, yogurt, kefir, rennet, etc.), eggs (egg, albumin, ovalbumin, lysozyme, mayonnaise), meat & poultry (all common meats, gelatin, collagen, animal fat), fish & seafood (fish, salmon, tuna, shrimp, lobster, oyster, etc.), insect-derived (carmine/E120, beeswax/E901, shellac/E904, honey, propolis, lanolin), non-vegan E-numbers

### Community features
- **Community feed**: see what other vegans are scanning, filter by country, today only, or following only
- **Ratings**: rate products 1–5 hearts
- **Contributions**: submit products not in the database; trusted contributors (Super Contributors) get instant approval
- **Feedback**: flag incorrect verdicts with photos and notes
- **Pioneer system**: tracked leaderboard of who first scanned each product (vegan products only)
- **Weekly challenges**: community-wide goals (e.g. "scan 5 new products this week")
- **Badges**: earned milestones (first scan, streaks, contributions, challenges)
- **Streak tracking**: consecutive days with at least one scan
- **Streak shields**: earned tokens that protect a missed day from breaking a streak
- **Referral system**: invite friends, both get extra daily scan quota

### Social
- Follow other vegans, see their scan feed
- Block users
- Public profile pages with stats, top-rated products, badges
- Follower/following counts

### Discovery
- **Trending products**: products with a scan spike in the last 6 hours vs the previous 6 hours
- **Top products leaderboard**: sortable by total scans or average rating, filterable by country and product category
- **Product categories**: sourced from Open Food Facts dataset
- **Brand profiles**: `is_fully_vegan` flag for brand-level discovery

---

## Subscription model

| Tier | Price | Limits |
|------|-------|--------|
| Free | €0 | 10 barcode scans/day (replenishes at midnight, extra earned via referrals and contributions) |
| Nom Nom Pro | ~€3/month | Unlimited scans, PRO badge, boosted community reputation |

Subscriptions managed via Google Play in-app purchases with server-side validation.

---

## API

**Base URL:** `https://nomnomvegan.com/api/`
**Authentication:** Firebase JWT — `Authorization: Bearer <token>` on all authenticated endpoints.

### Key endpoints

| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | `/health` | None | `{"status": "ok"}` — liveness check |
| GET | `/products/barcode/{barcode}` | Firebase | Main scan endpoint — returns verdict, product info, community stats |
| GET | `/products/barcode/{barcode}/detail` | Firebase | Full detail with photos, ratings |
| POST | `/history/record` | Firebase | Record a scan to search history |
| GET | `/history/mine` | Firebase | Paginated personal scan history |
| GET | `/history/mine/stats` | Firebase | Personal stats: streak, pioneer count, scan totals |
| GET | `/community/feed` | Firebase | Community scan feed (region, today_only, following_only params) |
| GET | `/community/top-products` | Firebase | Top products (period, region, sort_by, category params) |
| GET | `/community/trending` | Firebase | Products trending in the last 6 hours |
| GET | `/community/categories` | Firebase | Available product categories |
| POST | `/contributions/submit` | Firebase | Submit a new product to the community database |
| POST | `/feedback/submit` | Firebase | Submit a verdict correction with optional photos |
| POST | `/ratings/rate` | Firebase | Rate a product 1–5 hearts |
| GET | `/auth/me` | Firebase | Current user profile, daily quota, streak, badges |
| GET | `/auth/public/{alias}` | Optional Firebase | Public user profile page |
| GET | `/users/usage` | Firebase | Daily quota status |
| GET | `/badges/mine` | Firebase | Earned badges |
| GET | `/challenges/current` | Firebase | Current week's challenge and progress |
| POST | `/social/follow/{alias}` | Firebase | Follow a user |
| DELETE | `/social/unfollow/{alias}` | Firebase | Unfollow a user |
| GET | `/social/following` | Firebase | Users you follow |
| GET | `/social/followers` | Firebase | Users who follow you |
| GET | `/brands/search` | Firebase | Brand autocomplete search |
| POST | `/share/create` | Firebase | Create a shareable link |
| GET | `/share/view/{uuid}` | None | Public shared scan page |

### Quota and rate limiting

- Free scan quota is enforced server-side. Over-limit returns HTTP 429 with `{"error": "daily_limit_reached", ...}`.
- All write endpoints are rate-limited via slowapi (Redis-backed). Typical limits: 100–200 requests/hour.
- nginx rate limits: 60 requests/minute for API, 20 requests/minute for admin panel.

### Scan verdict response shape

```json
{
  "barcode": "string",
  "product_name": "string | null",
  "verdict": "vegan | not_vegan | uncertain",
  "confidence_score": 0.0,
  "source": "community | admin_override | off_tags | ocr | not_found",
  "non_vegan_ingredients": ["string"],
  "thumbs_up_count": 0,
  "thumbs_down_count": 0,
  "is_community": true,
  "photo_urls": ["string"],
  "pending_name": "string | null",
  "contribution_status": "string | null",
  "tags": ["string"]
}
```

---

## Technical stack

| Component | Technology |
|-----------|-----------|
| Mobile app | Kotlin + Jetpack Compose (Android) |
| Backend | Python 3.12, FastAPI, SQLAlchemy (async), Pydantic |
| Database | PostgreSQL 15, multi-schema (`app`, `users`, `queue`, `off`, `admin`) |
| Cache | Redis (results cache 24h TTL, rate limiting) |
| Auth | Firebase Admin SDK (Google Sign-In + email/password) |
| Photo storage | Cloudflare R2 (EU jurisdiction) |
| Async tasks | Celery + Redis broker |
| Web server | nginx (reverse proxy, SSL termination) |
| Blog | Ghost CMS |
| Hosting | Contabo VPS, Europe |
| Monitoring | Prometheus + Grafana |
| Error tracking | Sentry |

---

## Database schema overview

| Schema | Tables | Purpose |
|--------|--------|---------|
| `app` | `products`, `vegan_verdicts`, `product_ratings`, `brands` | Core product data |
| `users` | `accounts`, `reputation`, `daily_usage`, `badges`, `follows`, `blocks`, `challenge_progress` | User data |
| `queue` | `contributions`, `contribution_photos`, `feedback` | Community submissions |
| `off` | `products` | Read-only Open Food Facts mirror |
| `admin` | `users`, `audit_log` | Admin panel access |

---

## Company

**NomNomVegan Oy**
Registered in Finland
Contact: hello@nomnomvegan.com
Blog: https://nomnomvegan.com/blog
Privacy Policy: https://nomnomvegan.com/privacy
Terms of Service: https://nomnomvegan.com/terms
Google Play: https://play.google.com/store/apps/details?id=com.nomnomvegan.app
