From 6717ae071a15b54090850ffac24245de261bf5ce Mon Sep 17 00:00:00 2001 From: jwinterm Date: Thu, 9 Apr 2026 16:45:18 -0400 Subject: [PATCH] fix OG banner --- .../content/blog/vegan-iq-data-pipeline.mdx | 199 ++++++++++++++++++ .../images/branding/OG_banner_v2_light.png | Bin 0 -> 47594 bytes apps/web/src/app/layout.tsx | 20 ++ apps/web/src/app/links/page.tsx | 6 + apps/web/src/app/privacy/page.tsx | 5 + .../src/app/products/bauhaus-echo/page.tsx | 1 + apps/web/src/app/products/suchoice/page.tsx | 1 + apps/web/src/app/products/vegan-iq/page.tsx | 1 + apps/web/src/app/terms/page.tsx | 5 + 9 files changed, 238 insertions(+) create mode 100644 apps/web/content/blog/vegan-iq-data-pipeline.mdx create mode 100644 apps/web/public/images/branding/OG_banner_v2_light.png diff --git a/apps/web/content/blog/vegan-iq-data-pipeline.mdx b/apps/web/content/blog/vegan-iq-data-pipeline.mdx new file mode 100644 index 0000000..0733982 --- /dev/null +++ b/apps/web/content/blog/vegan-iq-data-pipeline.mdx @@ -0,0 +1,199 @@ +--- +title: "Building a Data-Driven Trivia Engine: No LLMs, Just Verified Facts" +date: "2026-04-09" +excerpt: "How we built Vegan IQ's question pipeline — deterministic generation from USDA, Oxford, and FAOSTAT data, quality filtering from 2,461 to 1,066 questions, and a greedy anti-repetition algorithm that makes every quiz feel fresh." +draft: true +--- + +Vegan IQ ships with 1,066 trivia questions. None of them were written by an LLM. Every question traces back to a specific data source — USDA FoodData Central, Poore & Nemecek (Science, 2018), NIH, or FAOSTAT. The pipeline that produces them is a deterministic Python script that generates questions from structured data, filters them for quality, and outputs a single JSON file that the Flutter app bundles as an asset. + +This post covers the full pipeline: data sourcing, question generation, quality filtering, and the runtime pacing algorithm that prevents repetitive quizzes. + +## The Data Layer + +All source data lives in a single Python module (`food_data.py`, ~2,800 lines). No API calls at generation time — everything is embedded as Python dicts and lists, verified against the original sources. + +### Nutritional Data (USDA FoodData Central) + +69 foods (56 vegan, 13 animal products), each with per-100g values for calories, protein, fat, carbs, fiber, iron, calcium, and vitamin C. The animal products exist so the app can generate fair head-to-head comparisons — "Which has more iron per 100g: hemp seeds or ground beef?" — where the plant food wins on data. + +### Environmental Impact (Poore & Nemecek, 2018) + +The largest meta-analysis of food systems ever published: 38,700 farms across 119 countries. We use their global mean values for GHG emissions (kg CO2eq/kg), land use (m2/kg), water use (liters/kg), and eutrophication (gPO4eq/kg) across 40 food products. + +### Other Sources + +- **NIH Office of Dietary Supplements** — RDA values, bioavailability, deficiency risks for B12, vitamin D, omega-3, iron, calcium +- **FAOSTAT** — top-3 producing countries and global production percentages for 45+ foods +- **Oxford Companion to Food** — etymology and historical origins for 60+ foods +- **FDA labeling guidelines** — 38 animal-derived ingredients (carmine, casein, confectioners glaze, etc.) +- **Faunalytics + peer-reviewed studies** — animal cognition and behavior research +- **USDA NASS** — retail prices for protein cost-efficiency comparisons + +## Question Generation + +`generate_questions.py` (~2,000 lines) contains 22 generator functions. Each takes structured data and outputs a list of question dicts. The script seeds Python's random with `seed(42)` so every run produces identical output. + +### Combinatorial Generators + +These produce the bulk of raw questions by iterating over food combinations: + +```python +# Simplified example of a per-100-calorie comparison generator +for combo in itertools.combinations(all_foods, 4): + if not _max_one_animal(combo): + continue + winner = max(combo, key=lambda f: f["protein_g"] / f["calories_kcal"] * 100) + if winner["protein_per_100cal"] < MINIMUM_MEANINGFUL["protein_g"]: + continue + # Generate question with 4 options, winner as correct answer +``` + +`_max_one_animal()` enforces at most one animal product per set of four options. This keeps the odds vegan-positive without making every question trivially obvious. + +### MINIMUM_MEANINGFUL Thresholds + +Early versions produced questions like "Which has the most protein per 100g?" where the winner had 2.5g. Technically correct. Completely uninteresting. The `MINIMUM_MEANINGFUL` dict gates all winners: + +| Nutrient | Threshold | +|----------|-----------| +| Protein | >= 5g | +| Fiber | >= 1g | +| Iron | >= 1.5mg | +| Calcium | >= 30mg | +| Vitamin C | >= 5mg | + +### Curated Generators + +Not everything is combinatorial. Hidden ingredient questions ("Is carmine vegan?"), food history questions ("Where did tempeh originate?"), and the "Would You Believe" two-truths format are hand-structured data fed through simpler generators. These produce more varied, narrative-style questions. + +### Vegan-Positive Framing + +When an animal product wins a nutrition comparison (34 of 1,066 questions), the explanation is reframed with environmental context: + +> "Chicken breast has 22.5g protein per 100g vs black beans at 8.9g. However, chicken costs 9.9 kg CO2eq, 12.2 m2 land, and 660L water per kg." + +Eight phrasing variants are randomly selected. The `isAnimalCorrect` boolean on the question model flags these for the app's UI to use muted feedback ("Technically correct..." instead of "Nailed it!"). + +## From 2,461 to 1,066: The Curation Step + +Raw generation produces 2,461 questions. The quality filter cuts this to 1,066 — a 43% acceptance rate. + +### Subcategory Caps + +The combinatorial generators are prolific. Without caps, "Which has the most protein per 100 calories?" would appear 160+ times with different food options. Same question text, different foods. After 3-4 of these in a quiz, it feels like a spreadsheet. + +Each template subcategory is capped: + +- Per-nutrient comparisons: 25 each +- Binary showdowns: 35-50 each +- Environment comparisons: 25 each + +This dropped the template-to-curated ratio from 77/23 to 43/57. In a 15-question quiz, roughly 6 are templated comparisons and 9 are diverse curated questions. + +### Scenario-Based Phrasings + +Even within caps, the same question text repeated 14+ times across a pool gets stale. Five phrasing variants per template type add surface variety: + +- "Which food has the most protein per 100 calories?" +- "Calorie for calorie, which food packs the most protein?" +- "You're counting calories but need maximum protein. Which delivers the most per 100 cal?" + +Same underlying data, different framing. Unique question texts went from ~30 to 658 across the pool. + +### primary_food Deduplication + +426 questions are tagged with a `primary_food` field (e.g., "tempeh", "mango"). The runtime pacing algorithm penalizes (-100) same-food questions within a single quiz. This prevents "Where did mango originate?" followed by "Which country produces the most mangoes?" + +### Plant Milk Exclusion + +Plant milks are ~90% water by weight. Per-kg environmental comparisons are misleading — oat milk looks absurdly efficient compared to almonds, but that's comparing a beverage to a solid food. A `_ENV_PER_KG_EXCLUDE` set filters all plant milks from the 5 environmental per-kg generators. Plant milks still appear in nutrition per-100g questions where the comparison is fair. + +## Runtime: The Pacing Algorithm + +Good questions don't matter if the quiz feels monotonous. The `QuestionService` in the Flutter app implements a greedy scoring algorithm that selects questions one at a time, penalizing candidates that would create repetitive sequences. + +### Four Levels of Deduplication + +1. **Session-level (hard block):** Questions shown in the current app session are never repeated. `_sessionSeenIds` is a `Set` reset on app restart. + +2. **Cross-session (soft penalty):** The last 300 question IDs are persisted in `SharedPreferences`. Questions in this set receive a -15 penalty but aren't blocked — you'll eventually cycle through the full pool. + +3. **Subcategory spacing:** No two adjacent questions can share a subcategory (-100 penalty). Two questions back: -60. Three back: -30. + +4. **Category spacing (all-categories mode):** If 3 of the last 5 questions share a category: -80 penalty. Same category as previous question: -40. + +### Scoring Candidates + +For each position in the quiz, the algorithm scores up to 60 candidates from the pool and picks the highest-scoring one: + +| Condition | Penalty | +|-----------|---------| +| Same subcategory as previous | -100 | +| Same question text as previous | -120 | +| Same `primaryFood` anywhere in sequence | -100 | +| Same category in 3 of last 5 | -80 | +| 3+ overlapping options with previous | -60 | +| Same subcategory 2 back | -60 | +| Same question text in last 5 | -50 | +| Same category as previous | -40 | +| Same subcategory 3 back | -30 | +| 2 overlapping options | -20 | +| Same category 2 of last 5 | -20 | +| In cross-session recent set | -15 | +| Switch between binary/multi-choice | +10 | + +The +10 bonus for format switching means quizzes alternate between swipe (true/false) and tap (multiple choice) questions, which keeps the interaction varied. + +### Pool Partitioning + +Before scoring, the pool is split into three tiers: + +1. **Preferred:** Not seen this session AND not in recent-300 +2. **Fallback:** In recent-300 (soft deprioritized via -15) +3. **Emergency:** Seen this session (only used if pools are exhausted) + +Preferred candidates are scored first. With 1,066 questions and 300 recent IDs tracked, the preferred pool stays above 700 for most users — enough for 40+ unique 15-question quizzes before any soft repeats. + +### Spaced Repetition + +Up to 3 questions the user previously answered incorrectly are pre-seeded into each quiz. These come from a missed-questions pool (max 200 entries) tracked in `SharedPreferences`, prioritizing questions missed 1-2 days ago. Correctly answering a review question removes it from the pool. + +### Complexity + +The greedy approach runs in O(count x min(poolSize, 60)) — well under a millisecond for 15-20 question quizzes on any modern phone. No noticeable latency between tapping a category and seeing the first question. + +## Output + +The pipeline outputs a single `questions.json` (623 KB, 1,066 entries). The Flutter app bundles this as an asset and caches it in memory on first load. No network requests, no server dependency, fully offline. + +```json +{ + "id": 42, + "category": "nutrition", + "subcategory": "protein_per_100cal", + "question": "Which has more protein per 100 calories: Soybeans or Cheddar Cheese?", + "options": ["Soybeans", "Cheddar Cheese"], + "correct_index": 0, + "explanation": "Soybeans: 9.6g per 100 cal vs Cheddar Cheese: 6.2g per 100 cal.", + "data_source": "USDA FoodData Central (SR Legacy)", + "primary_food": null, + "is_animal_correct": false +} +``` + +Every question carries its citation in `data_source`. The app displays this in the explanation screen after the user answers. No trust-me-bro — you can verify any answer against the original dataset. + +## What We Learned + +**Template fatigue is real.** The first version had 77% templated questions. Users noticed by quiz 3. Subcategory caps and phrasing variants were the fix. + +**Per-kg comparisons lie.** Comparing the environmental footprint of almonds (a solid) to oat milk (90% water) per kilogram is misleading. We had to exclude plant milks from per-kg environmental generators entirely. + +**The pacing algorithm matters more than the questions.** A great pool of 1,066 questions can feel repetitive if the selection is random. The greedy scoring approach — with its layered penalties for subcategory, category, text, option overlap, and primary food — is what makes each quiz feel curated. + +**Deterministic generation is underrated.** `seed(42)` means every team member, CI run, and release build produces the exact same question set. No drift, no surprises, no "the questions changed and I don't know why." + +The full pipeline — data → generators → quality filter → JSON → pacing engine — runs in under 2 seconds on a laptop. The output is a single file that ships with the app. No servers, no APIs, no LLMs. Just data. + +See the [Vegan IQ product page](/products/vegan-iq) for more. diff --git a/apps/web/public/images/branding/OG_banner_v2_light.png b/apps/web/public/images/branding/OG_banner_v2_light.png new file mode 100644 index 0000000000000000000000000000000000000000..2632eade4aef93012300406d85fed4b10f216abc GIT binary patch literal 47594 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

U>#(@@MijGqMu~CYl)kmTmamh6G7e#QV`YZL9pm zRvarrG85M&dCCo8yxw>JeO>M{=hUs`!ceU}Z>SG({LB0g#^#*Hp%g|;6XuyW5&&rE z|3Ak8PW=wJsvO$zL~1|ZRKVQfV?Lk(x-jCj0i@`f`6B;a!3X6IZ1#hg2dinTQM5K* z8uESU%>Slr%RHDS4BTkQFN5@6Q8eBYZHzW+WV0W}e9+hXmq8}ECmbs(P*VevT_<0` z!up#_G=r8c8C37XGDDhe$R|aXtS>4sWZrfkop}R<1*1Wuv?SK^6j&_$6Qc-2xJ*LP z;}bDpZiFb<0Gk~z%NfvQnE0ro{1@&)D}Si z4$+v9m13y0=d_K@ou>b?K$Iur@^KXePpu(o~%ZfE+qjT}BiTOYTF|DiN zK$=vQ9(vskAiL8_%%0JDbL) z=6Uf&7o7#71Mva6l6Xq(d5`H%NW%;DwFtum^5m*+(KoPfK*53u1qMjw9R=~cd-6sbP*wW`GLWv0rfW<81{@AEN(Dt!c1uRU7nb6 zyp61pK4I$gBG>Xo<*z`ZyTn&Q0Kv-jmG&qaLP3v%n!kPIwg&Xa_yGDNJ|sW#{+is) z-K2VYvY#8=8i0I>It@66R#grStUz;nkXJF52YGMGz>_%;O`xeU=W>+Yxdf$nU1Paw z7mnF%m4aX%XnPLC45JYklbFGVL|gEH%LdZM`w9y*s{E9{2LuWsj;-NhP3B>7QwhHq zdUdZIew-H7CPogu2Zk*3Kh?{Kjz3aapXuJ?;$Uku4U3DW(YhJ0qG<1~;)LiH>p9z7 zv#G#h6Vp%914F-XDycyRqfeBv)cz>pgx_oRICG|Ysqsg*vjUeqZG}%l)e<0Gib^A| z)dS*_TU?gyZc$2P@0ESG?*sh6_+^vnJ{o7AXDVg~RE^hnRpe#W=5Tkm*EC9Xp>=TD zRt4ipN{MNW39-J3kF)ImA}&$C`4OzGj|0-;)<6Uc(kSZwwnwq*6tOI*P=8_V1`Y8X zfH=fNHJBTT-sHxT%YvM(lY7;Hh!(Ad0+0|ffm`lmq*N5yOoWP_5Pmyuw+5UNTq|an z4PrhcW`nq3Rx~GNkJOhq4vuCN>uW8-;NaG7kDvzuzyDh|+%;pxYP(ZSNiLUr#|IN2I5Qq|M{7kuyf|ic&n~J>yQGFM^8(u3N%VVef%G zxYYqNS@CydyzC_N#26eE;2`8&CV2|W2OJbk(liEpfF_Bdt8VU16ThDMbIcvTm@Gn;T)$&8BDA2Epw%4CAFXiK9s!d~g%F#@{ zicz7lqsBnUjFFbV9$X1?ehf4$WaB7(a5Jz^lfpbO6q+5c&w zxKMOeZ@N7*`#D3IpwDxS9Evl=3Ty@(%N^e86mXCvbWWNC{|0VleDDPqzf(&BM{2fr z*dQ_|JnYqda`wWrGt_H)a(f;2p!D+U~99o8HvlJU_44s=!8n z?M58!LtijK5DlBwwcquOQ$tbJO>Atq@}|d-+8x)39O+-gLw-&O*}KW`eWWd5DN)|W zb}i0S*prP@9FjTcOiw65Ak!HEa|HX)qInW58XZW$CkW>K3O5GaJ#)sxpcaqml(Q@f z^cSu?W~a4*y<7!LJbUGp4G*V6`4SqSY2<&i!-9EVbx>i1T@ z4mL3a7m;Jih_auQ5di=NcVqO zcn7-CO@#&C>eOl_r~K-Yje}%9GRX%<8F+9Y&(^4Q4BZm_twZ)?d|1~N-=P2Tc8a4ZJW+o{FATJVV-A#-v4eRwW Gcm4;;D?4HU literal 0 HcmV?d00001 diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index eedaab9..3e53435 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -14,6 +14,26 @@ export const metadata: Metadata = { alternates: { canonical: "/", }, + openGraph: { + title: "Such Software", + description: "E-commerce infrastructure, custom app development, and accessible web applications.", + type: "website", + siteName: "Such Software", + images: [ + { + url: "/images/branding/OG_banner_v2_light.png", + width: 1200, + height: 630, + alt: "Such Software", + }, + ], + }, + twitter: { + card: "summary_large_image", + title: "Such Software", + description: "E-commerce infrastructure, custom app development, and accessible web applications.", + images: ["/images/branding/OG_banner_v2_light.png"], + }, icons: { icon: [ { url: "/images/branding/favicon_dark.svg", type: "image/svg+xml", media: "(prefers-color-scheme: dark)" }, diff --git a/apps/web/src/app/links/page.tsx b/apps/web/src/app/links/page.tsx index 880654c..7a3a5d2 100644 --- a/apps/web/src/app/links/page.tsx +++ b/apps/web/src/app/links/page.tsx @@ -9,6 +9,12 @@ export const metadata: Metadata = { title: "Links | Such Software", description: "Download our apps on App Store and Google Play.", alternates: { canonical: "/links" }, + openGraph: { + title: "Such Software Apps", + description: "Download our apps on App Store and Google Play.", + type: "website", + images: [{ url: "/images/branding/OG_banner_v2_light.png", width: 1200, height: 630, alt: "Such Software" }], + }, }; const apps = [ diff --git a/apps/web/src/app/privacy/page.tsx b/apps/web/src/app/privacy/page.tsx index 2efba19..9aefc00 100644 --- a/apps/web/src/app/privacy/page.tsx +++ b/apps/web/src/app/privacy/page.tsx @@ -7,6 +7,11 @@ export const metadata: Metadata = { title: "Privacy Policy | Such Software", description: "Privacy policy for Such Software LLC and its websites and applications.", alternates: { canonical: "/privacy" }, + openGraph: { + title: "Privacy Policy | Such Software", + description: "Privacy policy for Such Software LLC and its websites and applications.", + type: "website", + }, }; export default function PrivacyPage() { diff --git a/apps/web/src/app/products/bauhaus-echo/page.tsx b/apps/web/src/app/products/bauhaus-echo/page.tsx index 8252bd4..c39c80f 100644 --- a/apps/web/src/app/products/bauhaus-echo/page.tsx +++ b/apps/web/src/app/products/bauhaus-echo/page.tsx @@ -14,6 +14,7 @@ export const metadata: Metadata = { title: "Bauhaus Echo | Such Software", description: "Visual memory puzzle game inspired by Bauhaus design. Memorize, shuffle, reconstruct. Android, iOS, Web, Desktop.", type: "website", + images: [{ url: "/images/products/bauhaus-echo.png", width: 512, height: 512, alt: "Bauhaus Echo" }], }, }; diff --git a/apps/web/src/app/products/suchoice/page.tsx b/apps/web/src/app/products/suchoice/page.tsx index ec5a6d4..a05de96 100644 --- a/apps/web/src/app/products/suchoice/page.tsx +++ b/apps/web/src/app/products/suchoice/page.tsx @@ -14,6 +14,7 @@ export const metadata: Metadata = { title: "Suchoice | Such Software", description: "Can't decide? Snap a photo, let AI read your options, and pick for you. Decision tools for when you're stuck. Android and iOS.", type: "website", + images: [{ url: "/images/products/suchoice.png", width: 512, height: 512, alt: "Suchoice" }], }, }; diff --git a/apps/web/src/app/products/vegan-iq/page.tsx b/apps/web/src/app/products/vegan-iq/page.tsx index 56ed47c..22c3678 100644 --- a/apps/web/src/app/products/vegan-iq/page.tsx +++ b/apps/web/src/app/products/vegan-iq/page.tsx @@ -14,6 +14,7 @@ export const metadata: Metadata = { title: "Vegan IQ | Such Software", description: "Test your plant-based knowledge with 1000+ trivia questions across 8 categories. Swipe and tap gameplay with verified data. Android and iOS.", type: "website", + images: [{ url: "/images/products/vegan-iq.png", width: 512, height: 512, alt: "Vegan IQ" }], }, }; diff --git a/apps/web/src/app/terms/page.tsx b/apps/web/src/app/terms/page.tsx index dac627c..09042f0 100644 --- a/apps/web/src/app/terms/page.tsx +++ b/apps/web/src/app/terms/page.tsx @@ -7,6 +7,11 @@ export const metadata: Metadata = { title: "Terms of Service | Such Software", description: "Terms of service for Such Software LLC websites and applications.", alternates: { canonical: "/terms" }, + openGraph: { + title: "Terms of Service | Such Software", + description: "Terms of service for Such Software LLC websites and applications.", + type: "website", + }, }; export default function TermsPage() {