<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vineet J Karni</title>
    <description>The latest articles on DEV Community by Vineet J Karni (@vineetjk).</description>
    <link>https://dev.to/vineetjk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1196105%2Fcf0267f4-2871-4bc4-a153-50f6837a1d4a.jpeg</url>
      <title>DEV Community: Vineet J Karni</title>
      <link>https://dev.to/vineetjk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vineetjk"/>
    <language>en</language>
    <item>
      <title>Can Prithvi Eat This? A Food Companion I Built for My Friend Living in a PG</title>
      <dc:creator>Vineet J Karni</dc:creator>
      <pubDate>Sun, 04 Oct 2026 09:24:03 +0000</pubDate>
      <link>https://dev.to/vineetjk/can-prithvi-eat-this-a-food-companion-i-built-for-my-friend-living-in-a-pg-2nf</link>
      <guid>https://dev.to/vineetjk/can-prithvi-eat-this-a-food-companion-i-built-for-my-friend-living-in-a-pg-2nf</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;My friend &lt;strong&gt;Prithvi&lt;/strong&gt; lives in a PG (paying-guest accommodation). If you've lived in one, you know how food works there: the mess decides the menu, the kitchen isn't yours, and when the mess food doesn't work for you, the fallback is ordering in or grabbing something nearby.&lt;/p&gt;

&lt;p&gt;For most people that's just boring. For Prithvi it's hard, because her body has a few rules of its own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lactose bothers her, but only sometimes.&lt;/strong&gt; A little ghee is fine; a bowl of paneer in cream might not be.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;She has a sensitive gut.&lt;/strong&gt; Deep-fried, very spicy, or fizzy things can ruin her day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Her TSH is high (thyroid).&lt;/strong&gt; Soy and some millets are best limited.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;She's working on losing weight.&lt;/strong&gt; Fried snacks, sweets, and refined flour quietly add up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these is manageable on its own. The trouble is keeping all four in mind at once, every meal, with food she didn't cook. A mess dal is probably fine. The paneer butter masala on Sunday? The chole bhature someone orders for the floor? The masala chai? She can't always eat good food, so she needs a quick way to know which options are okay, which are okay in moderation, and how to make them better.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;AllergySafe Table&lt;/strong&gt;, a small app that answers one question in plain words: &lt;strong&gt;"Can Prithvi eat this?"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ask&lt;/strong&gt; in plain language by typing, speaking, or sending a photo: &lt;em&gt;"Can Prithvi eat paneer butter masala?"&lt;/em&gt; or &lt;em&gt;"What can she have for breakfast?"&lt;/em&gt; The answer comes back as a clear verdict, the reasons, easy swaps, and better options. It can also be read aloud.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan&lt;/strong&gt; a mess menu, a recipe, or a packaged-food label to see exactly which ingredients to watch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remix&lt;/strong&gt; a dish she loves into a version that suits her, swapping only what's needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt; dinners that suit her, with a shopping list, for the days she gets to cook or eat out with friends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt; keep track of what she loved and what didn't sit well, so her own experience builds up over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Under the hood, two open pieces work together: &lt;strong&gt;Google's open-weight Gemma 2, running locally through Ollama&lt;/strong&gt;, works out what's in a dish the app has never heard of, and a set of &lt;strong&gt;open, readable food rules&lt;/strong&gt; decides whether that suits her. The model fills in the recipe; it never gets to say "safe".&lt;/p&gt;

&lt;p&gt;It doesn't try to be a doctor. It's a friend who remembers all four of her rules, every single time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://allergysafe-table-web.onrender.com" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Try the live demo on Render&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;It's on Render's free plan, so the first visit can take up to a minute while the server wakes up. The hosted version runs the open food rules and ElevenLabs voice, but not Gemma (see Where it runs below), so for a dish outside its library it asks you for the ingredients. Try &lt;em&gt;"Can Prithvi eat paneer butter masala?"&lt;/em&gt; or &lt;em&gt;"What can she have for breakfast?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ask anything.&lt;/strong&gt; Her conditions are always visible, and the answer explains itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr4wr8xznmgse2dawezqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr4wr8xznmgse2dawezqn.png" alt="Asking whether Prithvi can eat paneer butter masala" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ask&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;th&gt;Dark mode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fasy3iqsswk32ha41i00s.png" alt="Ask screen" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F385fntfdrf8lgjmz47ku.png" alt="Answer with swaps" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkj9dtw0vl88udjzs95w5.png" alt="Dark mode answer" width="780" height="1688"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A dish the app has never seen.&lt;/strong&gt; Dabeli isn't in its recipe list, so Gemma 2 (on the same laptop) guesses the ingredients. The rules spot the butter and suggest a swap, and the app shows exactly what Gemma guessed so Prithvi can correct it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmwpalxedo9ft316zhwi2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmwpalxedo9ft316zhwi2.png" alt="Gemma 2 guessing what's in dabeli, and the rules flagging butter" width="800" height="1362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check a menu or a photo, remix a dish, plan dinners, and keep notes.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ingredient check&lt;/th&gt;
&lt;th&gt;Recipe remix&lt;/th&gt;
&lt;th&gt;Dinner plan&lt;/th&gt;
&lt;th&gt;Food notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2lunqxd9guley7kqwr4d.png" alt="Scan result" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1v187ty1coin8ok8yztg.png" alt="Remixed recipe" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5bn8suqzqbc4w5jfqqxr.png" alt="Dinner plan" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2jmu97zn0yq13yaxli8c.png" alt="Food notes" width="780" height="1688"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Her profile&lt;/strong&gt; explains what each condition means in everyday terms. It's editable, so the app also works for anyone else, including people with real food allergies like gluten or nuts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxuynbh50mvlzhy46ew7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxuynbh50mvlzhy46ew7e.png" alt="Prithvi's food profile" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/vineetjk" rel="noopener noreferrer"&gt;
        vineetjk
      &lt;/a&gt; / &lt;a href="https://github.com/vineetjk/AllergySafe" rel="noopener noreferrer"&gt;
        AllergySafe
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A friendly food companion built for a friend.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AllergySafe Table&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Can Prithvi eat this?&lt;/strong&gt; A friendly food companion built for a friend.&lt;/p&gt;
&lt;p&gt;My friend Prithvi is sometimes lactose intolerant, has a sensitive gut, has high TSH (thyroid), and is trying to lose weight. Keeping all four in mind every time we cook or order food is hard. AllergySafe Table answers the everyday question &lt;em&gt;"can she eat this?"&lt;/em&gt; in plain language, suggests easy swaps, and plans meals everyone can share.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Built for the Hacktoberfest Weekend Challenge: Build for a Friend (HF26).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://allergysafe-table-web.onrender.com" rel="nofollow noopener noreferrer"&gt;https://allergysafe-table-web.onrender.com&lt;/a&gt; (free Render plan, so the first visit can take up to a minute to wake up. The hosted version uses the rules only; Gemma runs when you run the app locally.)&lt;/p&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/vineetjk/AllergySafe/docs/screenshots/desktop-ask.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fvineetjk%2FAllergySafe%2FHEAD%2Fdocs%2Fscreenshots%2Fdesktop-ask.png" alt="Asking whether Prithvi can eat paneer butter masala on desktop" width="900"&gt;&lt;/a&gt;
&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Ask in plain words&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;Type, speak, or send a photo, for example &lt;em&gt;"Can Prithvi eat paneer butter masala?"&lt;/em&gt; or &lt;em&gt;"What can she have for breakfast?"&lt;/em&gt;. Each answer gives a clear verdict, the…&lt;/p&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/vineetjk/AllergySafe" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;&lt;br&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/vineetjk/AllergySafe.git
&lt;span class="nb"&gt;cd &lt;/span&gt;AllergySafe
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv backend/venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; backend/venv/bin/pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; backend/requirements.txt
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;frontend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;backend/.env.example backend/.env   &lt;span class="c"&gt;# optional: add an ElevenLabs key for voice&lt;/span&gt;

&lt;span class="c"&gt;# Optional, for dishes the app doesn't know: local Gemma 2 (about 1.6 GB)&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;ollama &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ollama serve &amp;amp;
ollama pull gemma2:2b

./start.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The stack:&lt;/strong&gt; a Next.js 16 frontend, a FastAPI backend, Gemma 2 (2B) through Ollama for unknown dishes, ElevenLabs for voice, and a Render Blueprint that deploys both services.&lt;/p&gt;
&lt;h3&gt;
  
  
  Rules, not guesses
&lt;/h3&gt;

&lt;p&gt;The heart of the app is a small, readable food engine, not a chatbot. When you ask about a dish, it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Works out what you mean.&lt;/strong&gt; It tells apart a dish ("can she eat rajma chawal?"), a list of ingredients, a request for ideas ("what can she have for breakfast?"), and a follow-up to its own question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Looks up typical ingredients&lt;/strong&gt; from a library of about 80 common Indian and international dishes, from dal makhani and masala dosa to pizza.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checks each ingredient&lt;/strong&gt; against her profile. Allergies (gluten, nuts, and so on) are marked &lt;strong&gt;not safe&lt;/strong&gt;. Her conditions (lactose, gut, thyroid, weight goal) are marked &lt;strong&gt;in moderation&lt;/strong&gt;, because that's what they are: things to limit, not things that will hurt her.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explains itself:&lt;/strong&gt; which ingredient caused each flag, a swap for each one, and a couple of healthier options.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Gemma fills in the dishes the rules don't know
&lt;/h3&gt;

&lt;p&gt;A library of 80 dishes will never cover everything a PG mess or a street stall serves. Before Gemma, asking about dabeli or misal pav got "I don't know, tell me the ingredients", which is the last thing you want to type at the counter.&lt;/p&gt;

&lt;p&gt;Now the backend asks &lt;strong&gt;Gemma 2 (2B), running locally in Ollama&lt;/strong&gt;, one narrow question: &lt;em&gt;what usually goes into this dish?&lt;/em&gt; It replies in strict JSON, and the backend validates it (2 to 12 short ingredient names, or &lt;code&gt;{"known": false}&lt;/code&gt; for anything that isn't food, so "can she eat my laptop" doesn't get a recipe). Those ingredients then go through the &lt;strong&gt;same rules&lt;/strong&gt; as everything else.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ingredients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;open_llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;suggest_ingredients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dish&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# Gemma 2: "what's in it?"
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FoodAssistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_analyse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dish&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assumed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# rules: "is it okay?"
&lt;/span&gt;    &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ingredients_source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;                    &lt;span class="c1"&gt;# shown to her in the app
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That split is deliberate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The model only guesses ingredients.&lt;/strong&gt; It never decides whether something is safe. The verdict always traces back to a rule anyone can read.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The guess is shown, not hidden.&lt;/strong&gt; The app says &lt;em&gt;"Ingredients guessed by gemma2:2b on this device: ..."&lt;/em&gt;, so Prithvi can see what it assumed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;She can correct it.&lt;/strong&gt; If Gemma is wrong, she types the real ingredients and the rules check again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A 2B model is wrong sometimes. It left the fried farsan off misal pav, and it thought malai kofta had meat. That's exactly why it doesn't get the final say. When Ollama isn't running, the app quietly falls back to asking her for the ingredients.&lt;/p&gt;
&lt;h4&gt;
  
  
  Where it runs
&lt;/h4&gt;

&lt;p&gt;Gemma runs on the same machine as the backend: a laptop on the same Wi-Fi, opened from a phone (&lt;code&gt;start.sh&lt;/code&gt; prints the address to open). The free Render demo has only 512 MB of RAM, too little for Gemma, so &lt;strong&gt;the &lt;a href="https://allergysafe-table-web.onrender.com" rel="noopener noreferrer"&gt;hosted demo&lt;/a&gt; uses the rules only&lt;/strong&gt;. To get the Gemma step, run the app locally with the commands above.&lt;/p&gt;
&lt;h3&gt;
  
  
  Indian food needed its own care
&lt;/h3&gt;

&lt;p&gt;Paneer, curd, malai, and lassi count as dairy. Ghee is nearly lactose-free, so it isn't flagged for an intolerance. "Peanut butter" and "coconut milk" are not dairy, and "stir-fried" is not "deep-fried". When neither the library nor Gemma knows a dish, it says so and asks what's in it, instead of pretending. For photos without an image model, it asks for the dish name rather than guessing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Voice that sounds like a person
&lt;/h3&gt;

&lt;p&gt;Prithvi can ask by voice and hear the answer, which matters when your hands are full or you're standing at the mess counter. Questions are transcribed with &lt;strong&gt;ElevenLabs Scribe&lt;/strong&gt;. Answers are spoken with &lt;strong&gt;Eleven v4 Turbo&lt;/strong&gt;, which is only available over a realtime websocket, so the backend streams the text, collects the audio, and returns a single clip. If that ever fails, it falls back to Turbo v2.5, so she still hears a real voice and not a robotic one.&lt;/p&gt;

&lt;p&gt;iPhones block audio that starts after a network request, so the app starts a tiny silent clip at the moment you tap and reuses it for the real answer. Small detail, big difference on a phone.&lt;/p&gt;
&lt;h3&gt;
  
  
  Built for a phone
&lt;/h3&gt;

&lt;p&gt;Prithvi will use this on her phone, so the whole app is a phone-first shell: a bottom tab bar where every section is always visible, a chat where only the conversation scrolls and the input stays put, and light and dark themes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Production details
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The browser only talks to the Next.js server, which forwards &lt;code&gt;/api/*&lt;/code&gt; to FastAPI, so there are no cross-origin or mixed-content issues on phones.&lt;/li&gt;
&lt;li&gt;Her profile and notes are stored &lt;strong&gt;only in her browser&lt;/strong&gt;, never on a shared server.&lt;/li&gt;
&lt;li&gt;Endpoints that spend ElevenLabs credits are rate-limited, and every input has a size limit.&lt;/li&gt;
&lt;li&gt;If the server is slow or down, the app shows a clear error. It never invents a "safe" verdict.&lt;/li&gt;
&lt;li&gt;GitHub Actions runs the backend tests on Python 3.11 to 3.13 and builds the frontend on every push.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Built with an agent
&lt;/h3&gt;

&lt;p&gt;I paired with Claude Code, connected to DEV through DevRelay. This curated session shows the moment we found that Gemma was configured but never actually called, and how we wired it in so the model guesses ingredients and the rules make the call:&lt;/p&gt;


&lt;div class="ltag-agent-session"&gt;
  &lt;div class="agent-session-header"&gt;
    
    &lt;span class="agent-session-tool-icon-badge" title="Claude Code"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;Wiring local Gemma 2 into AllergySafe Table for the Hacktoberfest Weekend Challenge&lt;/span&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-scroll"&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;i want to publish this application to challenge 1 of hf26 to dev&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaygetchallenges"&gt;mcp__devrelay-gateway__get_challenges&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{}&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Hacktoberfest Weekend Challenge: Build for a Friend. Prompt: build something with open-source AI at its core. Tag #hf26challenge. Due Oct 5, 06:59 UTC.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;grep -rniE "ollama|gemma|llama|llm" backend frontend/src&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ grep -rniE "ollama|gemma|llama|llm" backend frontend/src&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;backend/app/config.py: OLLAMA_MODEL = gemma2:2b ... backend/app/engine/llm_provider.py: class OpenLLMProvider&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Your submission is saved as a draft on DEV. One risk before you publish: the challenge prompt says 'Build something with open-source AI at its core', but the post says 'Rules, not guesses' and 'not a chatbot'. Your backend has an optional local Gemma 2 path through Ollama that the post never mentions. Add a Gemma section first, or publish as is?&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Add the Gemma/Ollama section first, then publish. and also the template was saying to add devrelay agent log to be attched is that possible? and also need a cover page to it&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cat app/engine/llm_provider.py; grep -rn "open_llm\|generate_with_gemma" app&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cat app/engine/llm_provider.py; grep -rn "open_llm\|generate_with_gemma" app&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;generate_with_gemma is defined but never called. meal_planner.py and recipe_remixer.py only call is_ollama_available() to set a label.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;I found a problem before writing anything: the app never actually calls Gemma. The planner and remixer only check whether Ollama is running, then change a label to 'Local open model via Ollama'. Every answer still comes from the rules engine. A section saying the app uses Gemma would be false.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-askuserquestion"&gt;AskUserQuestion&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Gemma is set up in the code but never used. How do you want to handle open-so...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Gemma is set up in the code but never used. How do you want to handle open-source AI in the submission?&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Wire Gemma in for real (Recommended)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Plan: when Prithvi asks about a dish the 80-dish library doesn't know, Gemma 2 running locally suggests the typical ingredients, and the open rules engine still decides the verdict. The model never says 'safe'. It only fills in what's in the dish.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;brew install ollama &amp;amp;&amp;amp; ollama serve &amp;amp; ollama pull gemma2:2b&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ brew install ollama &amp;amp;&amp;amp; ollama serve &amp;amp; ollama pull gemma2:2b&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;gemma2:2b  8ccf136fdd52  1.6 GB&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;llm_provider.py: add suggest_ingredients(dish) -&amp;gt; asks Gemma for strict JSON ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;llm_provider.py: add suggest_ingredients(dish) -&amp;gt; asks Gemma for strict JSON {known, ingredients}, validates 2-12 short names, caches per dish; send prompt via Ollama's own Gemma template instead of hand-written turn tokens&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;ok&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;but will the gemma running in the cloud? how about that? it will run in local but what about when its published?&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cat render.yaml&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cat render.yaml&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;plan: free (512 MB RAM) for both services&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;You're right. Gemma can't run on your current Render deploy: the free plan has 512 MB of RAM and Gemma 2 2B needs about 2-3 GB. Options: a hosted Gemma API, Hugging Face Inference, a paid Render instance running Ollama, or local only with an honest note in the post.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-askuserquestion"&gt;AskUserQuestion&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;How should the deployed (Render) app get Gemma?&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;How should the deployed (Render) app get Gemma?&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Local only, say so in the post&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;for d in 'malai kofta' 'misal pav' 'ragi mudde' 'asdfgh qwer' 'my laptop'; do...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ for d in 'malai kofta' 'misal pav' 'ragi mudde' 'asdfgh qwer' 'my laptop'; do suggest_ingredients $d; done&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;malai kofta ['meat', 'potato', 'cream', ...]
misal pav ['sprouted lentils', 'onion', 'tomatoes', ...]
asdfgh qwer []
my laptop []&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Gemma rejects nonsense correctly and gives reasonable lists for real dishes, but a 2B model makes mistakes: it put meat in malai kofta and left the fried farsan off misal pav. That's why it only guesses ingredients, the app shows the guess, and Prithvi can correct it.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;assistant.py: answer_with_open_model() calls Gemma only when the library has ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;assistant.py: answer_with_open_model() calls Gemma only when the library has no match, runs the guessed ingredients through the same rules, sets ingredients_source; planner/remixer labels fixed to 'Rule-based'; frontend shows 'Ingredients guessed by gemma2:2b on this device'&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;ok&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;pytest -q&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ pytest -q&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;25 passed (Gemma mocked: fills unknown dish, falls back without model, skips known dishes, JSON validation)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;curl localhost:8000/api/ask -d '{"message":"Can Prithvi eat dabeli?"}'&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ curl localhost:8000/api/ask -d '{"message":"Can Prithvi eat dabeli?"}'&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;CAUTION, ingredients_source gemma2:2b, concerns ['Butter has lactose.'], swap: a little ghee or olive oil&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Dabeli works end to end: Gemma lists butter, the rules flag lactose, and the answer is Caution with a swap. I took a screenshot of that, rendered a 1000x420 cover from real screenshots, added a Gemma section to the post (including that the free Render demo runs rules only), and pushed it all to GitHub.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-footer"&gt;
    &lt;span class="agent-session-meta"&gt;
        6 of 6 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Health details are personal.&lt;/strong&gt; Lactose, gut trouble, thyroid levels, and weight are things Prithvi shares with friends, not with an ad network or a model's training data. Gemma runs on the user's own machine, and it only ever sees a dish name, never her profile. The food checks use open rules, and her profile never leaves her browser. The only outside service is ElevenLabs, and only when she chooses to use voice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every answer can be checked.&lt;/strong&gt; A closed chatbot might say "a little cream is fine" with total confidence. In this app, every verdict traces back to a rule in a plain Python file that anyone can read. If something is wrong for her, like "curd is actually fine for me", it can be fixed in one line, by anyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's free to run and easy to extend.&lt;/strong&gt; Nobody living in a PG should need a monthly AI subscription to figure out dinner. Gemma 2 2B is a 1.6 GB download that runs on an ordinary laptop with no internet and no API key. Anyone can swap in a bigger open model with one setting (&lt;code&gt;OLLAMA_MODEL&lt;/code&gt;), add their own dishes or their mess's menu, or add another condition, and share it back.&lt;/p&gt;

&lt;p&gt;A closed API would have given me a clever chatbot that decides on its own what's safe. An open model plus open rules gave Prithvi something she can trust, understand, and change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma:&lt;/strong&gt; Gemma 2 (2B), running locally through Ollama, works out the ingredients of dishes the app doesn't know, as validated JSON. The open food rules then decide the verdict, so the model fills in knowledge but never makes the safety call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render:&lt;/strong&gt; the whole app ships as a Render Blueprint (&lt;code&gt;render.yaml&lt;/code&gt;) and is &lt;a href="https://allergysafe-table-web.onrender.com" rel="noopener noreferrer"&gt;live on Render&lt;/a&gt;. It deploys the FastAPI backend and the Next.js frontend as two services, with the frontend proxying API calls to the backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ElevenLabs:&lt;/strong&gt; voice questions use ElevenLabs Scribe for speech-to-text, and answers and recipe steps are read aloud with Eleven v4 Turbo over the realtime websocket, with a Turbo v2.5 fallback.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built with open source and a lot of care for a friend who deserves good food.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
