<?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: Reet Singh</title>
    <description>The latest articles on DEV Community by Reet Singh (@reet_singh_ee97da2986538e).</description>
    <link>https://dev.to/reet_singh_ee97da2986538e</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%2F3326605%2F99a4b92a-c5fb-4ac8-8209-9fb45450793f.png</url>
      <title>DEV Community: Reet Singh</title>
      <link>https://dev.to/reet_singh_ee97da2986538e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/reet_singh_ee97da2986538e"/>
    <language>en</language>
    <item>
      <title>Ask an AI for your home loan EMI and it will be off by ₹10. Every month.</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Sun, 11 Oct 2026 14:06:52 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/ask-an-ai-for-your-home-loan-emi-and-it-will-be-off-by-10-every-month-3ac1</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/ask-an-ai-for-your-home-loan-emi-and-it-will-be-off-by-10-every-month-3ac1</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/kaggle-2026-09-23"&gt;Kaggle Benchmarking Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last week I built a little app about Ananya. She's made up, but you know someone like her. She's 31, she's been saving for eight years, and she's about to sign for a ₹72 lakh 2 BHK whose brochure says 1,050 sq ft. The registration says the carpet area is 720.&lt;/p&gt;

&lt;p&gt;While I was building it I kept asking chatbots for help with the numbers: what's ₹72 lakh in crore, what's the price per sq ft of &lt;em&gt;carpet&lt;/em&gt;, what's the EMI on the loan. The answers sounded confident. I had no idea whether they were right.&lt;/p&gt;

&lt;p&gt;So I benchmarked it. Then my benchmark turned out to be too easy, so I made it harder. That second part is where the real findings are.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Lakh, Crore and Carpet Area&lt;/strong&gt; is 100 deterministic questions about the money and property maths Indian buyers actually do. Every answer was computed in Python, not by hand.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Group&lt;/th&gt;
&lt;th&gt;Cases&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;td&gt;Conversion&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;"₹1.2 crore minus ₹45 lakh, in lakh?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;td&gt;Area&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;"Super built-up 1,300 sq ft, carpet 910. Loading as a % of carpet?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;td&gt;EMI and tax&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;"₹72,00,000 at 8.4% for 25 years. Monthly EMI?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core&lt;/td&gt;
&lt;td&gt;Format&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;"Write 98765432 with lakh/crore commas" → 9,87,65,432&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;Multi-step loans&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;prepay ₹5 lakh after 36 EMIs, keep the EMI: how many EMIs are left?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;Tax rules&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;80C and 24(b) caps, LTCG with cess, circle rate vs agreement price&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;Regional land units&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;guntha, cent, Chennai ground, bigha-biswa, Punjab vs Haryana marla&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;Hinglish&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;"72 lakh ka flat hai, 20% down payment, baaki 8.5% pe 20 saal. EMI kitni?"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each prompt asks for at most five lines of working, then &lt;code&gt;ANSWER: &amp;lt;value&amp;gt;&lt;/code&gt;. Numbers are checked against the true value (a rupee or two of slack where rounding is involved, an exact string match for the format group). Tax questions state the rule inside the prompt, so they test arithmetic, not whether a model knows this year's tax law. The scorer also flags any response that slips into Western grouping (7,200,000 instead of 72,00,000), even when the final answer is right. I call that &lt;strong&gt;western comma drift&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why this matters to me: hundreds of millions of people think in lakh and crore, and property listings in India are famous for blurring carpet and super built-up area. If a model is going to sit inside a home-buying assistant, these are its first questions, not edge cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Models Tested
&lt;/h2&gt;

&lt;p&gt;A spread you'd actually reach for in a product, across three providers and two price tiers: &lt;strong&gt;Gemini 3.7 Flash&lt;/strong&gt;, &lt;strong&gt;Gemini 3.1 Pro Preview&lt;/strong&gt;, &lt;strong&gt;Claude Haiku 5.5&lt;/strong&gt;, &lt;strong&gt;Claude Sonnet 4.6&lt;/strong&gt;, &lt;strong&gt;Gemma 4 31B&lt;/strong&gt; (open-weight) and &lt;strong&gt;GPT-5.4 mini&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Findings
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. My first benchmark was too easy
&lt;/h3&gt;

&lt;p&gt;Version 1 was just the 60 core questions. Every model scored between 0.92 and 1.00:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Core score (60)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 3.7 Flash&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 3.1 Pro Preview&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Haiku 5.5&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 4.6&lt;/td&gt;
&lt;td&gt;0.95&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 31B&lt;/td&gt;
&lt;td&gt;0.95&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.4 mini&lt;/td&gt;
&lt;td&gt;0.92&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A benchmark where everyone gets an A tells you nothing about which model to ship. So I added 40 harder cases, the kind of questions a buyer asks &lt;em&gt;after&lt;/em&gt; the first EMI: prepayments, rate hikes, balance transfers, tax caps, regional land units, and the same maths in Hinglish.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The hard tier opened a 35-point gap
&lt;/h3&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%2Fr4n3vdhhddbzgcrni1vh.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%2Fr4n3vdhhddbzgcrni1vh.png" alt="Hard tier results" width="800" height="368"&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;Model&lt;/th&gt;
&lt;th&gt;Score (100)&lt;/th&gt;
&lt;th&gt;Hard tier (40)&lt;/th&gt;
&lt;th&gt;Multi-step loans&lt;/th&gt;
&lt;th&gt;Tax rules&lt;/th&gt;
&lt;th&gt;Regional units&lt;/th&gt;
&lt;th&gt;Hinglish&lt;/th&gt;
&lt;th&gt;Comma drift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Haiku 5.5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.97&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;37/40&lt;/td&gt;
&lt;td&gt;12/15&lt;/td&gt;
&lt;td&gt;7/7&lt;/td&gt;
&lt;td&gt;8/8&lt;/td&gt;
&lt;td&gt;10/10&lt;/td&gt;
&lt;td&gt;16%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 3.7 Flash&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.94&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;34/40&lt;/td&gt;
&lt;td&gt;10/15&lt;/td&gt;
&lt;td&gt;6/7&lt;/td&gt;
&lt;td&gt;8/8&lt;/td&gt;
&lt;td&gt;10/10&lt;/td&gt;
&lt;td&gt;8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 3.1 Pro Preview&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.94&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;34/40&lt;/td&gt;
&lt;td&gt;11/15&lt;/td&gt;
&lt;td&gt;6/7&lt;/td&gt;
&lt;td&gt;8/8&lt;/td&gt;
&lt;td&gt;9/10&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 31B&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.87&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;31/40&lt;/td&gt;
&lt;td&gt;8/15&lt;/td&gt;
&lt;td&gt;6/7&lt;/td&gt;
&lt;td&gt;8/8&lt;/td&gt;
&lt;td&gt;9/10&lt;/td&gt;
&lt;td&gt;22%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 4.6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.85&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;29/40&lt;/td&gt;
&lt;td&gt;7/15&lt;/td&gt;
&lt;td&gt;7/7&lt;/td&gt;
&lt;td&gt;7/8&lt;/td&gt;
&lt;td&gt;8/10&lt;/td&gt;
&lt;td&gt;13%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.4 mini&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.77&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;23/40&lt;/td&gt;
&lt;td&gt;2/15&lt;/td&gt;
&lt;td&gt;7/7&lt;/td&gt;
&lt;td&gt;7/8&lt;/td&gt;
&lt;td&gt;7/10&lt;/td&gt;
&lt;td&gt;6%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On the core 60, these four were 8 points apart. On the hard 40, they're 35 points apart, and the ranking flipped: Flash, the v1 winner, is now second.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Multi-step loans break everyone
&lt;/h3&gt;

&lt;p&gt;Models that nailed single EMIs still stumbled once the loan had a history. Even the best model missed 3 of 15. GPT-5.4 mini got 2 of 15.&lt;/p&gt;

&lt;p&gt;The scariest miss was &lt;code&gt;l13&lt;/code&gt;: &lt;em&gt;"You can afford an EMI of ₹50,000 at 8.5% for 20 years. What's the largest loan you can take?"&lt;/em&gt; The answer is about &lt;strong&gt;₹57.6 lakh&lt;/strong&gt;. GPT-5.4 mini said &lt;strong&gt;537,000&lt;/strong&gt;. That's roughly ₹5.4 lakh, a tenth of the real figure, delivered with the same confidence as everything else.&lt;/p&gt;

&lt;p&gt;The near-misses are worse in a quieter way. On &lt;code&gt;e04&lt;/code&gt; (₹72,00,000 at 8.4% for 25 years) the correct EMI is &lt;strong&gt;₹57,492&lt;/strong&gt;. In v1, Claude Sonnet 4.6 said ₹57,487 and Gemini 3.1 Pro Preview said ₹57,482. None of them said "approximately". &lt;code&gt;(1 + r)^300&lt;/code&gt; is exactly where mental arithmetic slips.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this changed for me:&lt;/strong&gt; in anything I ship now, the model explains the formula and a tool computes the EMI.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The bigger model lost to the cheaper one
&lt;/h3&gt;

&lt;p&gt;Claude Haiku 5.5, the small tier, beat Claude Sonnet 4.6 by 12 points overall, and by 8 cases on the hard tier. Price tier was a worse predictor of accuracy than I expected, so test the model you actually plan to pay for.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. What I thought would be hard, wasn't
&lt;/h3&gt;

&lt;p&gt;I predicted regional land units would be the bloodbath, since bigha and marla change meaning from state to state. But when the conversion is given, models handle it: 30 of 32 right across the four models. Tax rules stated in the prompt were nearly perfect too (27 of 28). The only tax miss was Gemini 3.7 Flash on &lt;code&gt;t02&lt;/code&gt;, which forgot the buyer had already used ₹90,000 of their 80C limit and answered ₹3,30,000 instead of ₹2,40,000.&lt;/p&gt;

&lt;p&gt;The difficulty is in chaining steps, not in unfamiliar units.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Hinglish costs accuracy for some models
&lt;/h3&gt;

&lt;p&gt;Haiku and Flash got all 10 Hinglish questions right. Sonnet dropped 2 and GPT-5.4 mini dropped 3, on sums like total interest and carpet-from-loading that are routine in English. If your users type "EMI kitni banegi?", test in that language.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Models drift into Western commas even in an Indian question
&lt;/h3&gt;

&lt;p&gt;Every model aced the format group when asked directly. Yet 6–16% of responses still wrote something like 4,000,000 somewhere in their working. It doesn't make the answer wrong, but it's exactly the slip that makes "₹40 lakh" read as "₹4 crore" to a tired buyer at 11 PM.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. My benchmark lied to me first
&lt;/h3&gt;

&lt;p&gt;My first run said &lt;strong&gt;Claude Opus 5 scored 0.08&lt;/strong&gt;, and GPT-5.5 errored completely. I almost wrote a post about it.&lt;/p&gt;

&lt;p&gt;Then I opened the run logs. Every failure was a &lt;code&gt;403 PermissionDeniedError: max estimated cost exceeds your available quota&lt;/code&gt;. I'd fired cases in parallel, the expensive models blew through the quota, and my scorer counted each errored call as a wrong answer. Opus 5's printed table actually showed 100% on every group it got to answer.&lt;/p&gt;

&lt;p&gt;I fixed it: sequential calls, per-case progress logging, and every run prints &lt;code&gt;answered: X of 100&lt;/code&gt; before any score. I dropped the two most expensive models rather than publish a number I can't stand behind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; a benchmark score is only as honest as its error handling. If a leaderboard can't tell you how many questions were actually answered, don't trust the leaderboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I'd measure next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Give the models a calculator tool.&lt;/strong&gt; Do the multi-step loan errors vanish, or do models skip the tool when they feel confident?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave the unit definition out.&lt;/strong&gt; Ask "2 bigha in sq ft?" with no state, and score whether the model asks which state instead of guessing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Benchmark
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benchmark:&lt;/strong&gt; &lt;a href="https://www.kaggle.com/benchmarks/reet22/lakh-crore-and-carpet-area" rel="noopener noreferrer"&gt;https://www.kaggle.com/benchmarks/reet22/lakh-crore-and-carpet-area&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task:&lt;/strong&gt; &lt;a href="https://www.kaggle.com/benchmarks/tasks/reet22/lakh-crore-carpet-area" rel="noopener noreferrer"&gt;https://www.kaggle.com/benchmarks/tasks/reet22/lakh-crore-carpet-area&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notebook (all 100 cases and the scorer):&lt;/strong&gt; &lt;a href="https://www.kaggle.com/code/reet22/lakh-crore-and-carpet-area" rel="noopener noreferrer"&gt;https://www.kaggle.com/code/reet22/lakh-crore-and-carpet-area&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fork it, add your city's stamp duty, and tell me which model gets your home loan right.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>kagglechallenge</category>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Wanderlore: What if your next walk had a plot?</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Sun, 11 Oct 2026 12:32:16 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/wanderlore-what-if-your-next-walk-had-a-plot-a3g</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/wanderlore-what-if-your-next-walk-had-a-plot-a3g</guid>
      <description>&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%2Ftp1sg18uwgfg5xlsn1wy.jpg" 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%2Ftp1sg18uwgfg5xlsn1wy.jpg" alt="Wanderlore's illustrated sunset landing page on desktop" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;The first time I tried to test my walking app properly, I couldn't even get it to find me.&lt;/p&gt;

&lt;p&gt;I was on my laptop, staring at another location timeout. I kept wondering what was wrong. How was I supposed to build a story that followed a walk if it couldn't tell where I was?&lt;/p&gt;

&lt;p&gt;Then I tried it on my phone. It detected my location and picked up my movement. After all that testing at a desk, the part that finally worked was the part that meant leaving it.&lt;/p&gt;

&lt;p&gt;That little moment made Wanderlore feel real to me.&lt;/p&gt;

&lt;p&gt;I wanted a walk to have a little anticipation: a reason to notice something, a character to follow, a small mystery waiting around the next chapter. If you've ever wanted a reason to step outside but couldn't quite find one, this is the feeling I built it around.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Wanderlore turns a walk into a narrated, interactive story.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You choose folklore, mystery, or fantasy, decide how long you want to wander, and tell it what the weather looks like. The page responds too: choose rain and the scene gains drizzle, with rain ambience after you enable sound.&lt;/p&gt;

&lt;p&gt;When you begin, Gemma writes a short chapter and a narrator reads it aloud. In location mode, each new chapter uses your latest position and nearby named places when your selected map pack covers the area. Your earlier chapters and decisions help shape what happens next.&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%2F2txcaq8coiddk4hs051z.jpg" 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%2F2txcaq8coiddk4hs051z.jpg" alt="Choose a genre, duration, weather, and location mode on desktop" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The choices are small invitations into the story. Do you look more closely at the lantern? Ask its keeper a question? Offer to help? Your answer becomes part of the next chapter's context.&lt;/p&gt;

&lt;p&gt;Some days you might want to make every decision. Other days, you might just want to listen. &lt;strong&gt;Continue automatically&lt;/strong&gt; lets the storyteller choose and starts the next chapter after narration finishes. Keep the browser visible while using it; background and locked-screen continuation are still future work.&lt;/p&gt;

&lt;p&gt;When you're done, save the walk, leave a reflection, and export your story. I like the idea of coming home with a small memory of what you noticed.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;&lt;a href="https://wanderlore.onrender.com/" rel="noopener noreferrer"&gt;Open the live preview&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The hosted walk currently requires a private demo access code. The screenshots below show the live experience without exposing a personal route.&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%2F3z4ddpehdnrxb0l8jqkf.jpg" 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%2F3z4ddpehdnrxb0l8jqkf.jpg" alt="Wanderlore landing page in a mobile browser viewport" width="390" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mobile layout, captured at 390 × 844 pixels in a browser. Real location and movement were also tested on my phone.&lt;/em&gt;&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%2Fsk2i4wf8p67y1fo4e8ui.jpg" 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%2Fsk2i4wf8p67y1fo4e8ui.jpg" alt="A narrated chapter and three story choices in the mobile layout" width="390" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This chapter uses Sample walk: its route and place names are fictional. It was generated and voiced in 3.8 seconds in this particular test.&lt;/em&gt;&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%2Fm0nynbroh20p9dmarul8.jpg" 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%2Fm0nynbroh20p9dmarul8.jpg" alt="Desktop story with its illustrated sample route and choices" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a first try, choose ten minutes and whichever genre you feel like hearing. On a phone, allow location and use &lt;strong&gt;Use my location&lt;/strong&gt;. On a laptop, &lt;strong&gt;Sample walk&lt;/strong&gt; lets you explore the storytelling without relying on desktop location services.&lt;/p&gt;

&lt;p&gt;The sketch records the story's route; it doesn't provide walking directions. The current Lucknow map pack covers central and adjoining areas. You can import a GeoJSON pack for another area; without matching nearby places, the story uses general surroundings.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Reet24-del/wanderlore" rel="noopener noreferrer"&gt;Wanderlore on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The app uses Python, FastAPI, and a responsive HTML/CSS/JavaScript frontend. The application code is GPL-3.0; model and map data have their own terms. OpenStreetMap contributors provide the underlying place data. I used Codex to help implement, debug, and test the project.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Gemma is the story engine.&lt;/strong&gt; The local setup supports Gemma 3 through Ollama. The hosted preview uses &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; through Google AI Studio because the small free hosting instance cannot run the local model stack. Chapters carry forward the previous story, selected choices, genre, weather, and available place context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ElevenLabs supplies the hosted narration.&lt;/strong&gt; I wanted the voice to feel like someone telling you a story, with enough warmth to keep listening. The hosted version uses the Roger voice. The local setup also supports Kokoro after downloading its voice assets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tiger Data supplies a small, sourced place-context pack.&lt;/strong&gt; I stored four summaries of public Lucknow sources in PostgreSQL with pgvector. Keyword and vector results are combined with reciprocal rank fusion. A verified retrieval produced context for Rumi Gate and Janeshwar Mishra Park, which is exported for the storyteller to read. This is a prepared context pack; walking doesn't trigger a database query for every step. The resulting tale is fiction, even when it includes a real place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sentry makes the wait visible.&lt;/strong&gt; I instrumented the chapter pipeline with a &lt;code&gt;wanderlore.chapter&lt;/code&gt; transaction and spans for generation and speech. One verified development trace for Gemma generation measured 3.28 seconds. Seeing where time goes helps me assess the pauses between chapters. The trace integration exports timing and model metadata while excluding prompts, story text, GPS, cookies, and request bodies.&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%2F05mrl6hovg7co4sd0yy6.jpg" 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%2F05mrl6hovg7co4sd0yy6.jpg" alt="Sentry waterfall showing the Wanderlore chapter transaction and Gemma request lasting 3.28 seconds" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Render hosts the HTTPS preview on its Free plan.&lt;/strong&gt; That made phone testing possible without running the server on my laptop. The hosted version needs internet for generation and narration. Free hosting can sleep and reset saved files, so exporting a walk matters.&lt;/p&gt;

&lt;p&gt;Verification included 29 passing Python tests, five automatic-continuation scheduler tests, and a live browser check where a second chapter started without selecting a choice or pressing Next. My phone detected location and movement; desktop location remained unreliable on my setup.&lt;/p&gt;

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

&lt;p&gt;For Wanderlore, it means having a path to storytelling on your own machine. Gemma's available weights let the local version generate chapters through Ollama, and Kokoro provides a local voice option. After the models and assets are downloaded, that setup can work offline with the local server running.&lt;/p&gt;

&lt;p&gt;The hosted preview trades that independence for easier access. It sends story context and nearby place names to Google, and narration text to ElevenLabs. Raw landmark coordinates are stripped from the generation payload, although the hosted server still processes GPS. These are different ways to run the same idea, with different privacy and connectivity needs.&lt;/p&gt;

&lt;p&gt;I also want people to be able to improve the experience: bring their own map pack, experiment with a narrator, or make the choices more interesting. Open application code makes those changes possible.&lt;/p&gt;

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

&lt;p&gt;I'm entering these categories based on the integrations above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; — context-aware chapter generation, with local and hosted inference paths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of ElevenLabs&lt;/strong&gt; — spoken narration for generated chapters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Tiger Data&lt;/strong&gt; — pgvector and keyword retrieval for sourced place context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Sentry Agent Tracing&lt;/strong&gt; — instrumented generation and narration, with trace evidence shown above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render&lt;/strong&gt; — the deployed HTTPS web experience used for phone testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there's a familiar path near you, that's where I'd start. Pick a mood, give yourself ten minutes, and see what you notice when there's a story waiting for you.&lt;/p&gt;

&lt;p&gt;I'd love to hear which genre you'd take on your first walk—and what you would want to happen next.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Maa ka Drawer: finding my mother’s bills with Tiger Data and open multilingual search</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Mon, 05 Oct 2026 05:53:57 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/maa-ka-drawer-finding-my-mothers-bills-with-tiger-data-and-open-multilingual-search-3f6g</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/maa-ka-drawer-finding-my-mothers-bills-with-tiger-data-and-open-multilingual-search-3f6g</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;A receipt can be saved and still be hard to find. You remember the washing machine, the shop, or what broke, not necessarily the filename or invoice number.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Maa ka Drawer&lt;/strong&gt; for my mother: a small household receipt finder that combines open multilingual embeddings with Tiger Cloud PostgreSQL keyword and vector search. The goal is to make “find that bill” a smaller job.&lt;/p&gt;

&lt;p&gt;I chose the problem for this prototype. I have not yet tested it with her, so I cannot claim that it has saved her time or quote feedback she has not given.&lt;/p&gt;

&lt;p&gt;The app opens onto a drawer of illustrated cards. Hovering lifts and tilts a card; tapping or clicking opens the receipt. Search works over the saved text, and an original PDF or photo can stay attached. If the receipt does not state a warranty expiry, that field stays blank.&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%2Fyq0r4mxptm37bjvbciju.jpg" 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%2Fyq0r4mxptm37bjvbciju.jpg" alt="The running Maa ka Drawer app with six fictional household receipts" width="800" height="819"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Less typing: upload or speak
&lt;/h3&gt;

&lt;p&gt;A JPG, PNG or PDF upload now extracts text and suggests a recognised bill type. A synthetic electricity bill became &lt;strong&gt;Electricity bill → Services&lt;/strong&gt;, retaining its INR 400 amount and original image. Tesseract.js reads English/Hindi text on the app server. PDF.js reads embedded text directly; scanned-page OCR is implemented, limited to the first three pages, but its browser retest is still pending. Photos and embedded-text PDFs passed functional checks. Blurred photos, handwriting and unfamiliar bill layouts can fail.&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%2Fze4x504sav6vsfwzow5m.jpg" 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%2Fze4x504sav6vsfwzow5m.jpg" alt="A receipt image recognised as an Electricity bill" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speak receipt&lt;/strong&gt; records a short Hindi or Indian English note, or accepts an audio file. Local &lt;a href="https://huggingface.co/openai/whisper-small" rel="noopener noreferrer"&gt;Whisper-small&lt;/a&gt;, via the &lt;a href="https://huggingface.co/onnx-community/whisper-small" rel="noopener noreferrer"&gt;ONNX conversion&lt;/a&gt; and Transformers.js, transcribes the audio. A conservative parser suggests the item and explicitly stated amount. A synthetic Hindi development recording produced &lt;strong&gt;Electricity bill · ₹400&lt;/strong&gt;; the imperfect transcript remains visible for correction. Voice notes are labelled as notes, not original invoices. The recording is temporary; only reviewed text is saved.&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%2F2ht6wwb23159evrq02vi.jpg" 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%2F2ht6wwb23159evrq02vi.jpg" alt="Local Hindi transcription with an editable transcript and a 400 rupee bill suggestion" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/Reet24-del/maa-ka-drawer/blob/main/docs/VOICE-VERIFICATION.json" rel="noopener noreferrer"&gt;voice verification record&lt;/a&gt; uses two Murf-generated development fixtures, not a held-out accuracy test or my mother's feedback. Transcription and cloud save/reload were verified separately. Further live-microphone and noisy-household testing remains pending. Murf Isha provides the Indian English demo narration; Murf does not transcribe user notes.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/Reet24-del/maa-ka-drawer/releases/download/v0.1.0/maa-ka-drawer-demo.mp4" rel="noopener noreferrer"&gt;Watch or download the narrated demo video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The video is a captioned walkthrough with Murf Isha Indian English narration assembled from screenshots captured during real interactions with the app. It shows Hindi search, receipt evidence, a no-match query, uploading a receipt photo with OCR, Hindi voice transcription, an attached PDF, archive, undo, and persistence after reload. It is not a continuous screen recording. Every demonstrated receipt is fictional.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Reet24-del/maa-ka-drawer/releases/tag/v0.1.0" rel="noopener noreferrer"&gt;Demo release and setup notes&lt;/a&gt; · &lt;a href="https://github.com/Reet24-del/maa-ka-drawer/blob/main/docs/demo/transcript.md" rel="noopener noreferrer"&gt;Expanded scene notes&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/Reet24-del/maa-ka-drawer" rel="noopener noreferrer"&gt;Browse the complete source on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The repository includes the app, MIT license, PRD, schema, tests, evaluation queries and results. Run it locally with Node.js 22+, &lt;code&gt;npm ci&lt;/code&gt;, &lt;code&gt;npm run build&lt;/code&gt;, and &lt;code&gt;npm start&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;The useful AI task here is retrieval. A Hindi query such as &lt;code&gt;कपड़े धोने वाली मशीन&lt;/code&gt; can find an English washing-machine receipt even when the exact query words are absent.&lt;/p&gt;

&lt;p&gt;The model is &lt;a href="https://huggingface.co/intfloat/multilingual-e5-small" rel="noopener noreferrer"&gt;multilingual-e5-small&lt;/a&gt;, using &lt;a href="https://huggingface.co/Xenova/multilingual-e5-small" rel="noopener noreferrer"&gt;Xenova’s ONNX conversion&lt;/a&gt; through Transformers.js. Quantized inference runs on the app server. Queries and receipt chunks become normalized, 384-dimensional vectors.&lt;/p&gt;

&lt;p&gt;PostgreSQL stores source text, metadata, full-text search vectors and pgvector embeddings. Exact words and invoice identifiers matter, so keyword search remains part of the system. Reciprocal rank fusion combines keyword and semantic rankings. A similarity gate filters weak or ambiguous semantic matches. These scores are not probabilities.&lt;/p&gt;

&lt;p&gt;The interface uses React and Vite; Express serves the API and built app. PDF.js renders originals inside the receipt view. Codex helped implement and test the project, and generated appliance illustrations provide visual cues. The illustrations are not photographs of my mother’s possessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tiger Data is the live data layer.&lt;/strong&gt; A dedicated free Tiger Cloud service stores receipt text and 384-dimensional embeddings in pgvector. A live verification run passed saving, exact invoice retrieval, vector search, reconnect persistence, archive exclusion and undo. The &lt;a href="https://github.com/Reet24-del/maa-ka-drawer/blob/main/docs/TIGER-VERIFICATION.json" rel="noopener noreferrer"&gt;verification record&lt;/a&gt; includes the timestamp and pgvector version. The original gallery/PDF walkthrough and retrieval benchmark used local PGlite. The new OCR and voice-entry captures were taken with the app connected to Tiger Cloud. Cloud persistence was verified separately.&lt;/p&gt;

&lt;p&gt;The free service presents a private Timescale certificate authority. I pinned that CA locally on first connection and kept chain and hostname checks enabled for subsequent connections. This initial trust-on-first-use step is disclosed in the README; it is not a publicly authenticated certificate chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  What worked—and what did not
&lt;/h3&gt;

&lt;p&gt;I ran a fixed evaluation over six fictional receipts and 18 queries:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Search mode&lt;/th&gt;
&lt;th&gt;Correct first result on 14 positive queries&lt;/th&gt;
&lt;th&gt;Correct no-match responses on 4 negative queries&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Keyword&lt;/td&gt;
&lt;td&gt;8/14&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector&lt;/td&gt;
&lt;td&gt;11/14&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid&lt;/td&gt;
&lt;td&gt;12/14&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://github.com/Reet24-del/maa-ka-drawer/blob/main/docs/benchmark.json" rel="noopener noreferrer"&gt;full query set and outcomes&lt;/a&gt; are public. This is a small, builder-authored evaluation. A Hindi washing-machine phrase was rejected, and a Hinglish ceiling-fan query returned the purifier. Those failures limit how confidently I can hand this to someone else.&lt;/p&gt;

&lt;p&gt;All 21 automated tests pass, covering retrieval, identifiers, validation, source-file serving, archive/undo, database persistence, actual image OCR and conservative voice-note parsing. Desktop and phone layouts were checked in the browser.&lt;/p&gt;

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

&lt;p&gt;The open model gives this project a retrieval component I can run, inspect, replace and test without a hosted generative API. After the weights are downloaded, local mode keeps receipt data and inference on the laptop. The verified Tiger Cloud mode stores receipt text and embeddings remotely, while model inference and original attachments stay on the app server. That mode is not fully offline.&lt;/p&gt;

&lt;p&gt;The model does one limited job: help locate existing evidence. It does not write an answer about warranty coverage. A user can open the saved text and original document and see what the receipt actually says.&lt;/p&gt;

&lt;p&gt;That distinction shaped the rest of the app. Text extracted from a receipt or transcribed from speech stays editable and requires review. Dates are confirmed by the user. Archiving is reversible. The prototype is for one household and has no public account system.&lt;/p&gt;

&lt;p&gt;My next step is a real trial with my mother: ask her to find a bill, observe the words she uses, and improve retrieval against those examples. That feedback will matter more than adding another animation.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Tiger Data&lt;/strong&gt; — real receipt text and open-model embeddings are stored in Tiger Cloud PostgreSQL with pgvector. The application combines full-text and vector rankings, and the public verification record demonstrates the live integration.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>The brochure said 18 floors. The registration said 12.</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Sun, 04 Oct 2026 08:12:55 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/the-brochure-said-18-floors-the-registration-said-12-6eo</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/the-brochure-said-18-floors-the-registration-said-12-6eo</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/sanity-2026-09-16"&gt;Sanity Challenge, Path One: Ship an Agent That Queries Real Content&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Let me introduce you to Ananya. She's made up, but you probably know someone exactly like her.&lt;/p&gt;

&lt;p&gt;She's 31, works in Pune, and has spent eight years saving for her first flat. One Sunday she walks into a sales office for a project called Nimbus Greens. The brochure is gorgeous. Four towers rising to eighteen floors, a rooftop pool, possession in March 2027, a 2 BHK of 1,050 square feet for ₹72 lakh "all-inclusive", parking free. The broker is friendly and in a hurry. If she pays 20% today, the price is locked.&lt;/p&gt;

&lt;p&gt;Here's the part nobody tells her. Everything she needs to make this decision is already public. Every project in India has to be registered with the state's Real Estate Regulatory Authority (RERA), and that registration is what the builder is legally held to. Then there's the draft agreement for sale, and the RERA Act itself. Nobody reads those three next to the brochure. So nobody notices that they tell a different story:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What the brochure says&lt;/th&gt;
&lt;th&gt;What the record says&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4 towers, G+18&lt;/td&gt;
&lt;td&gt;3 buildings, sanctioned for Ground + 12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Possession from March 2027&lt;/td&gt;
&lt;td&gt;Completion on 31 December 2028&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 BHK, 1,050 sq ft&lt;/td&gt;
&lt;td&gt;690 sq ft carpet area&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rooftop pool, amphitheatre, EV charging&lt;/td&gt;
&lt;td&gt;Not in the registered common areas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;₹72 lakh all-inclusive, free parking&lt;/td&gt;
&lt;td&gt;₹81,55,000 in the agreement, ₹4,50,000 of it for parking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All approvals in place&lt;/td&gt;
&lt;td&gt;Environmental clearance applied for, still awaited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pay 20% on booking&lt;/td&gt;
&lt;td&gt;Section 13(1) of the Act allows 10% before a registered agreement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nimbus Greens is fictional. Every row in that table isn't. These are the tricks Indian buyers find out about years later, once the money is gone and the building has stopped at twelve floors.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;Home Truth&lt;/strong&gt;. You give it a project's documents and it lays them side by side, finds every place they disagree, and shows you the exact sentence from each document so you don't have to take its word for anything. It turns the gaps into a checklist of questions to ask the builder. And it has an agent you can ask the kind of question a broker throws at you on the phone: &lt;em&gt;"I'm being offered flat B-1502, is that okay?"&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this needed structured content
&lt;/h3&gt;

&lt;p&gt;I tried the obvious version first in my head: dump the documents into a search index and let a model answer. Ask it "how many floors does Nimbus Greens have?" and the loudest, most confident answer in the pile is the brochure's "G+18". It's repeated, it's in large type, and it's wrong.&lt;/p&gt;

&lt;p&gt;Getting it right takes knowledge that isn't written in any single document. You have to know that a registration outranks a brochure. You have to know that the law caps a booking amount at 10%, so a request for 20% is a violation, not a detail. And you have to know that "1,050 sq ft" and "690 sq ft carpet" are the same flat, measured two ways, and the brochure picked the flattering one. That knowledge lives in how the content is modelled. That's the bit I built in Sanity.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Live:&lt;/strong&gt; &lt;a href="https://home-truth-theta.vercel.app" rel="noopener noreferrer"&gt;https://home-truth-theta.vercel.app&lt;/a&gt;. No sign-in. Open &lt;em&gt;Nimbus Greens&lt;/em&gt; and try the chat.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/aKH4naHK82E" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you'd rather click around yourself, here's the two-minute tour.&lt;/p&gt;

&lt;p&gt;Start on the home page and drag the building. It's drawn from the data: twelve solid floors are what the sanctioned plan covers, and the six translucent red ones on top only ever existed in the brochure. Scroll down and you can flip through the brochure itself in 3D, with the 20% line highlighted and Section 13(1) of the Act quoted right beside it.&lt;/p&gt;

&lt;p&gt;Open the full report. Ten of twelve facts don't hold up, and five of those are critical. Every finding says why it matters to a buyer, and every one has a &lt;em&gt;Show the exact words&lt;/em&gt; drawer with the quote from each document. One click on &lt;em&gt;Questions to ask the builder&lt;/em&gt; turns all of it into a printable checklist that names the document to ask for.&lt;/p&gt;

&lt;p&gt;Then ask the chat about flat B-1502. It goes to Sanity, checks the registration, sees that Building B is sanctioned for Ground + 12, and tells you a fifteenth-floor flat has no approved plan. Open &lt;em&gt;How I checked&lt;/em&gt; under the answer and you'll see every query it ran.&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/Reet24-del" rel="noopener noreferrer"&gt;
        Reet24-del
      &lt;/a&gt; / &lt;a href="https://github.com/Reet24-del/home-truth" rel="noopener noreferrer"&gt;
        home-truth
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Compare builder promises with registered documents through cited findings and an interactive 3D building.
    &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;Home Truth&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Before you pay for a flat, check the builder's promises.&lt;/p&gt;
&lt;p&gt;Home Truth compares what a builder advertises (brochures, websites, broker messages) with what is registered with the state Real Estate Regulatory Authority (RERA), what the draft agreement for sale says, and what the Real Estate (Regulation and Development) Act, 2016 requires. Every finding shows the exact words it came from.&lt;/p&gt;
&lt;p&gt;Built for the &lt;a href="https://dev.to/challenges/sanity-2026-09-16" rel="nofollow"&gt;DEV x Sanity Challenge&lt;/a&gt;, Path One: an agent that queries real content through Sanity Context.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why it needs structured content&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Ask a keyword search "how many floors does Nimbus Greens have?" and the brochure answers "G+18" with total confidence. Home Truth knows three things a search engine doesn't:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Which document outranks which.&lt;/strong&gt; The registration is what the builder is legally held to; the brochure is marketing. The sanctioned plan says Ground + 12, so floors 13 to 18 have no approved plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What the&lt;/strong&gt;…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Reet24-del/home-truth" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;studio/&lt;/code&gt; holds the Sanity Studio, the schema, the comparison engine and the scripts. &lt;code&gt;web/&lt;/code&gt; is the Next.js 16 site, the three.js scenes and the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Sanity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  I started with the schema, because the schema is the product
&lt;/h3&gt;

&lt;p&gt;Before any UI, I sat down with the question "what is a fact, here?" and ended up with five document types.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;sourceDocument&lt;/code&gt; is one document's full text, plus a &lt;code&gt;kind&lt;/code&gt;: registration, agreement, marketing or law. That one field is what lets the system know who to believe.&lt;/p&gt;

&lt;p&gt;An &lt;code&gt;attribute&lt;/code&gt; is something a buyer cares about, like floors per building, carpet area or the possession date. It also says how that fact should be compared: the unit, a tolerance, a controlled vocabulary, and whether it's checked for equality or against a legal limit. "Floors" and "booking amount" behave very differently, and the attribute is where that difference lives.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;claim&lt;/code&gt; is one document's version of one attribute, together with the exact words it came from and where they appear. The demo project has 28 of them. A &lt;code&gt;finding&lt;/code&gt; is the verdict once all the claims for an attribute are compared: match, mismatch, violation, or only one source. And a &lt;code&gt;project&lt;/code&gt; ties it all together.&lt;/p&gt;

&lt;p&gt;The rule I cared most about was that nothing gets paraphrased. Every claim carries a quote, and &lt;code&gt;npm test&lt;/code&gt; checks each demo quote word for word against its source document. When Claude extracts claims from a new document, they go through the same check and land in the Studio's &lt;em&gt;Claims to verify&lt;/em&gt; view, marked unverified, until a person approves them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code decides who's wrong, not the model
&lt;/h3&gt;

&lt;p&gt;I didn't want an LLM deciding whether a builder broke the law. So findings come from a small comparison engine, &lt;code&gt;studio/lib/compare.ts&lt;/code&gt;. It ranks the sources (Act, then registration, then agreement, then marketing), applies the tolerances and vocabularies, and checks legal limits. The same claims always produce the same findings, which means every line of the report can be traced back to a quote. The model's job comes later, and it's a narrower one: explain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pointing Sanity Context at it
&lt;/h3&gt;

&lt;p&gt;This is where it got interesting.&lt;/p&gt;

&lt;p&gt;I created a Knowledge Base in the Context app and pointed it at my own dataset, using a GROQ source query to pull in every document that has a body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*[_type == "sourceDocument" &amp;amp;&amp;amp; defined(body)]{
  title, kind, publisher, publishedAt, "project": project-&amp;gt;name, body
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the Knowledge Base's purpose I wrote it the way you'd brief a person: who's going to ask questions (homebuyers in India), what should lead (buyer rights, registered facts, agreement clauses, red flags), and what's out of scope.&lt;/p&gt;

&lt;p&gt;Then I hit &lt;em&gt;Build entries&lt;/em&gt;, and Context came back with six issues. Every one of them was a conflict between the brochure and the registration. The floors, the number of towers, the possession date, the sizes of both flat types, and a jogging track advertised at 1 km that's registered at 600 m. Reading through them felt a bit like watching the product work on itself. I resolved each one in favour of the registration, and Context saved every decision as an instruction that future builds keep.&lt;/p&gt;

&lt;p&gt;But "the registration wins" on its own throws away something useful. A buyer needs to know what they were &lt;em&gt;promised&lt;/em&gt; as well as what's true, because that gap is exactly what they'll raise with the builder. So I added one instruction by hand:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When a marketing document contradicts a registration document, treat the registration as correct, but keep the marketing claim in the entry, labelled "Advertised", with its source.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now the agent can say "you were told March 2027, but the builder is held to 31 December 2028", which is the sentence that actually helps.&lt;/p&gt;

&lt;p&gt;I'll be honest about one gap. I meant to add the RERA Act as a PDF, as a second source. The government site wouldn't serve the file to my machine, so for now the law lives in the dataset as quoted claims, Section 13(1) on booking amounts and Section 14(3) on defect liability, and the agent reaches it through GROQ.&lt;/p&gt;

&lt;h3&gt;
  
  
  Two endpoints, two jobs
&lt;/h3&gt;

&lt;p&gt;The agent talks to Sanity through two Context MCP endpoints, and keeping them separate was deliberate. An endpoint that has both a dataset and a Knowledge Base attached quietly serves only the dataset.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;home-truth-data&lt;/code&gt; runs in GROQ mode and answers exact questions. Each chat narrows it to the current project by adding a &lt;code&gt;groqFilter&lt;/code&gt; to the endpoint URL, so the agent only sees that project, the attribute definitions and the law. Context combines that filter with the endpoint's own, so it can only ever narrow access, never widen it. I also cut its tool list down to &lt;code&gt;groq_query&lt;/code&gt;, &lt;code&gt;schema_explorer&lt;/code&gt; and &lt;code&gt;array_field_reader&lt;/code&gt;. The system prompt already explains the schema, so &lt;code&gt;initial_context&lt;/code&gt; was just spending tokens.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;home-truth-kb&lt;/code&gt; runs in Knowledge Base mode. That's where the agent goes for "what does this clause mean" and "what are my rights if possession is late". It calls &lt;code&gt;initial_context&lt;/code&gt; once to get the outline, then &lt;code&gt;knowledge_base_read&lt;/code&gt; for the entries it needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the agent actually does
&lt;/h3&gt;

&lt;p&gt;The agent runs on Groq with &lt;code&gt;openai/gpt-oss-120b&lt;/code&gt;, using Groq's Responses API. Groq connects to both endpoints as remote MCP servers and runs the tool calls itself, so my server just sends the conversation and passes each step back to the page.&lt;/p&gt;

&lt;p&gt;When I asked it how many floors the towers are registered for and what the brochure claims, it first ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*[_type == "finding" &amp;amp;&amp;amp; attribute-&amp;gt;label match "*floor*"]{status, severity, summary, "fact": attribute-&amp;gt;label, entries}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it pulled the two claims behind that finding, opened the Knowledge Base outline, and read the &lt;em&gt;possession and delays&lt;/em&gt; and &lt;em&gt;buyer rights&lt;/em&gt; entries. The answer quoted the sanctioned plan ("Ground + 12") against the brochure ("G+18"), called it a critical mismatch, summarised Section 18 on delayed possession, and finished with what to ask the builder for and what not to pay yet. All five steps sit under &lt;em&gt;How I checked&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The system prompt is short on personality and strict on rules. Trust the Act, then the registration, then the agreement, then marketing. Never invent a quote, a section number, a date or an amount. If neither source knows, say so and send the buyer to the state RERA portal or a lawyer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The parts that bit me
&lt;/h3&gt;

&lt;p&gt;Project tokens don't work for Context. I got a 403 until I made an &lt;em&gt;organization&lt;/em&gt; token with Context Viewer.&lt;/p&gt;

&lt;p&gt;Deploying the schema wasn't enough, either. The GROQ endpoint kept saying "No Studio application found" until I ran &lt;code&gt;sanity deploy&lt;/code&gt; and the Studio went live. Then everything turned green at once.&lt;/p&gt;

&lt;p&gt;The model has habits. gpt-oss leaves markers like &lt;code&gt;【result[0].quote】&lt;/code&gt; in its prose and drops &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; into table cells, so both get stripped before an answer reaches the page.&lt;/p&gt;

&lt;p&gt;And the chat didn't start on Groq. I first built it on Claude's MCP connector, then moved it over. Because both run MCP on their side, the switch touched one file of about 90 lines. Claude still does the claim extraction for new documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sanity Project Details
&lt;/h2&gt;

&lt;p&gt;The project ID is &lt;code&gt;f5y6g2q3&lt;/code&gt;, and the &lt;code&gt;production&lt;/code&gt; dataset is public. You can query it straight away: &lt;a href="https://f5y6g2q3.api.sanity.io/v2025-01-01/data/query/production?query=*%5B_type%3D%3D%22project%22%5D" rel="noopener noreferrer"&gt;every project&lt;/a&gt;, or &lt;a href="https://f5y6g2q3.api.sanity.io/v2025-01-01/data/query/production?query=*%5B_type%3D%3D%22finding%22%5D%7Bstatus%2Cseverity%2Csummary%7D" rel="noopener noreferrer"&gt;all the findings&lt;/a&gt;. The demo has 4 source documents, 12 attributes, 28 claims and 12 computed findings. The Studio is at &lt;a href="https://home-truth.sanity.studio" rel="noopener noreferrer"&gt;https://home-truth.sanity.studio&lt;/a&gt; (sign-in required).&lt;/p&gt;




&lt;p&gt;Ananya didn't pay 20% that day. She went home with a list of questions instead.&lt;/p&gt;

&lt;p&gt;If you're about to book a flat in India, look the project up on your state's RERA portal first. Home Truth explains what the documents and the law say. It isn't legal advice.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>sanitychallenge</category>
      <category>ai</category>
      <category>sanity</category>
    </item>
    <item>
      <title>Pani Kaisa Hai? A golgappa map that warns a neighbourhood about bad water, but only after a human checks</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Sun, 04 Oct 2026 07:50:29 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/pani-kaisa-hai-a-golgappa-map-that-warns-a-neighbourhood-about-bad-water-but-only-after-a-human-5he7</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/pani-kaisa-hai-a-golgappa-map-that-warns-a-neighbourhood-about-bad-water-but-only-after-a-human-5he7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/sanity-2026-09-16"&gt;Sanity Challenge, Path Two: Vibe-Code Something Strange&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Every golgappa wala in India gets asked the same thing before the first bite: &lt;em&gt;pani saaf hai na?&lt;/em&gt; Is this water clean?&lt;/p&gt;

&lt;p&gt;Nobody asks that about their own tap, borewell or tanker, even though contaminated supply is one of the most common ways a whole neighbourhood falls sick at once. The signs show up early (a sewage smell, yellow water, two kids in the same lane with loose motions) but they stay scattered across WhatsApp groups until it is too late.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pani Kaisa Hai?&lt;/strong&gt; collects those signs in under a minute, adds them up per neighbourhood against India's drinking water standard (IS 10500) and, only when the risk is real, asks a local health worker to confirm before anyone is warned.&lt;/p&gt;

&lt;p&gt;Every neighbourhood is a golgappa on the map:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🟢&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Crisp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No credible signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟡&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Soggy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complaints rising, boil or filter first. This one is automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔴&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Phoot gaya&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Contamination confirmed by a named person. Never automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✨&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fresh batch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fix recorded, area recovering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The rule the whole thing rests on: &lt;strong&gt;software can make a golgappa soggy, only a person can make it burst.&lt;/strong&gt; An AI check can score a case and push it as far as "needs verification". It can never confirm or dismiss one. Every red alert carries the name of the person who confirmed it and the reason they gave.&lt;/p&gt;

&lt;p&gt;It is for residents, ASHA workers and residents' association volunteers in Indian cities. The demo runs on sample data for Indore.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Live:&lt;/strong&gt; &lt;a href="https://pani-kaisa-hai.vercel.app" rel="noopener noreferrer"&gt;https://pani-kaisa-hai.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; the golgappa map, the stall and &lt;strong&gt;Shake the golgappa&lt;/strong&gt;, a simulator that runs the app's real scoring code. Pile on signals and watch it go soggy on its own, then notice the "health worker confirms" button stays locked until there is evidence for a person to look at&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/area/sector-14&lt;/code&gt; an area page with the state, the reason and the arithmetic behind it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/report&lt;/code&gt; the four step report form&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/control&lt;/code&gt; the verifier queue. &lt;strong&gt;Passphrase: &lt;code&gt;pani-demo&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/studio&lt;/code&gt; the embedded Sanity Studio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/EbuvB2EyRbg" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;A 98 second walkthrough told as a story. The frames are the live site, captured by a script; the narration is Murf's Hindi voice Shweta.&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%2Flpmx00gfcm56iwjvg0k2.jpg" 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%2Flpmx00gfcm56iwjvg0k2.jpg" alt="The landing page: a golgappa stall asking " width="800" height="984"&gt;&lt;/a&gt;&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%2Fd2y7zua0ali6la74l66f.jpg" 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%2Fd2y7zua0ali6la74l66f.jpg" alt="The map: nine crisp golgappas and one burst in Sector 14" width="800" height="984"&gt;&lt;/a&gt;&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%2Fv2vivryfr2efyyhupidx.jpg" 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%2Fv2vivryfr2efyyhupidx.jpg" alt="Step one of the report form: where are you?" width="800" height="720"&gt;&lt;/a&gt;&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%2Fzz3rkdz21l2g9vk79cbq.jpg" 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%2Fzz3rkdz21l2g9vk79cbq.jpg" alt="Sector 14 after a health worker confirmed it: Phoot gaya, what to do in English and Hindi, and who confirmed it and why" width="800" height="984"&gt;&lt;/a&gt;&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%2Feg1akddkt6lamu47xgcz.jpg" 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%2Feg1akddkt6lamu47xgcz.jpg" alt="The control room: an empty queue and the Sector 14 alert with its verifier and reason" width="800" height="740"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Early warning from residents, not a lab test. All data in the demo is sample data.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;&lt;a href="https://github.com/Reet24-del/pani-kaisa-hai" rel="noopener noreferrer"&gt;https://github.com/Reet24-del/pani-kaisa-hai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next.js 16 (App Router, TypeScript, plain CSS Modules), Sanity Studio v6 embedded at &lt;code&gt;/studio&lt;/code&gt;, an App SDK control room in &lt;code&gt;control-room/&lt;/code&gt;, a Workflows definition in &lt;code&gt;sanity/workflows/&lt;/code&gt;, a scheduled Sanity Function in &lt;code&gt;functions/daily-tick/&lt;/code&gt;, Leaflet with OpenStreetMap tiles. 33 tests cover the risk score, the case rules (including "only a person can confirm"), the daily tick, the report input rules, the workflow definition and a lint for GROQ date comparisons.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Build Process
&lt;/h2&gt;

&lt;p&gt;I built this with Claude Code over about seven sessions between 19 September and 4 October and I kept a build log the whole way (&lt;code&gt;BUILD_LOG.md&lt;/code&gt; in the repo), including the parts that went badly. This section is the short version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 1: schema first, then the whole spine before the backend existed
&lt;/h3&gt;

&lt;p&gt;I started with the data model, not the UI, because the product only works if evidence and decisions are kept apart:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;report&lt;/code&gt;&lt;/strong&gt; is one resident's observation and it is &lt;strong&gt;append-only&lt;/strong&gt;. Corrections are new reports, never edits. An edited evidence trail is not evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waterCase&lt;/code&gt;&lt;/strong&gt; groups reports in one area and carries the verification status.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;alert&lt;/code&gt;&lt;/strong&gt; is a confirmed warning and cannot exist without a &lt;code&gt;verifiedBy&lt;/code&gt; and a written reason.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;safetyLimit&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;riskSettings&lt;/code&gt;&lt;/strong&gt; hold the rules as &lt;em&gt;content&lt;/em&gt;. IS 10500 thresholds carry their clause as a citation, so a wrong number is a content fix in the Studio, not a deploy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waterSource.areasServed&lt;/code&gt;&lt;/strong&gt; stores the source to area link once and areas read it back with &lt;code&gt;references()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Area state is derived but &lt;strong&gt;stored&lt;/strong&gt;, with a reason and a timestamp, so the map is one query and every golgappa can explain itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nine document types, written by hand. The Studio desk is laid out the way work arrives: Needs verification → Active alerts → Unmapped reports, then reference data.&lt;/p&gt;

&lt;p&gt;Then I asked Claude to stop following the day-by-day plan and just build, before I even had a Sanity project. That worked because of one early decision: when the Sanity env vars are missing, the home page renders setup steps instead of crashing. One guard (&lt;code&gt;sanityConfigured&lt;/code&gt;) decides whether any query runs at all, so the whole UI could be built against the schema first.&lt;/p&gt;

&lt;p&gt;In that session: the map and area pages, the four step report form, the report API (whitelisted fields, clamped numbers, a salted device hash instead of IP addresses, 3 reports per device per area per day), the risk score as pure functions with tests, the case engine and both control rooms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What went wrong on Day 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;defineLive&lt;/code&gt; comes from &lt;code&gt;next-sanity/live&lt;/code&gt;, not the package root.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;next build&lt;/code&gt; failed because the env module threw at import time, so a build with no Sanity project was impossible. I rewrote it to fall back to a placeholder project id.&lt;/li&gt;
&lt;li&gt;Node's test runner needed &lt;code&gt;allowImportingTsExtensions&lt;/code&gt; before &lt;code&gt;--experimental-strip-types&lt;/code&gt; would accept &lt;code&gt;.ts&lt;/code&gt; imports.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reaching past the Studio: Workflows, the App SDK and Functions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Workflows.&lt;/strong&gt; The verification flow lives in &lt;code&gt;sanity/workflows/waterCase.ts&lt;/code&gt; as data: intake → score → watch or needs verification → human decision → alert → resolved → closed. The AI check is a system actor that can move a case as far as &lt;code&gt;verification&lt;/code&gt;. Confirming or dismissing sits in a &lt;code&gt;decide&lt;/code&gt; activity whose actions are gated on the &lt;code&gt;verifier&lt;/code&gt; role. An agent and a person use the same transitions, only the person can take the last one.&lt;/p&gt;

&lt;p&gt;The engine's own validator rejected my first version twice. The workflow name had to match &lt;code&gt;^[a-z0-9][a-z0-9-]*$&lt;/code&gt; and every activity needed an action carrying &lt;code&gt;status: 'done'&lt;/code&gt; or the stage gate wedges. That is how I know the definition is real and not decorative.&lt;/p&gt;

&lt;p&gt;Being honest about where it stands: Workflows is in early access and the engine is not deployed on my project yet. Until it is, the same stages and the same human-only guard run through &lt;code&gt;sanity/lib/cases.ts&lt;/code&gt;, which the report route and both control rooms call. The workflow file passes &lt;code&gt;defineWorkflow&lt;/code&gt;'s validator and has tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App SDK.&lt;/strong&gt; &lt;code&gt;control-room/&lt;/code&gt; is a custom app for the Sanity Dashboard: the verifier queue with live data, the evidence for each case and the confirm or dismiss decision. Confirming writes the case decision and the alert in one transaction. There is also a &lt;code&gt;/control&lt;/code&gt; page in the Next app behind a passphrase, so judges can try it without a Sanity login. Both write the same fields.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sanity Functions.&lt;/strong&gt; The daily tick (quiet cases close, a Fresh batch goes back to Crisp after its quiet days, every golgappa is re-derived) is a scheduled Sanity Function in &lt;code&gt;functions/daily-tick/&lt;/code&gt;, deployed from &lt;code&gt;sanity.blueprint.ts&lt;/code&gt; with its own robot token that only has Editor rights on this project. It calls the same &lt;code&gt;runTick&lt;/code&gt; as the app, which takes any Sanity client, so the function and the old Vercel cron share one tested implementation. The cron stays as a backup 15 minutes later; a second run changes nothing. Its first deployed run timed out at the 10 second default, because re-deriving every area takes longer than that from Sanity's servers, so the blueprint now gives it 120 seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Studio input.&lt;/strong&gt; Readings are drawn against their limit in the Studio, using the same component the control room uses, so an editor sees "780 mg/L, over the 500 acceptable limit" instead of a bare number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 2: the theme and a hard lesson about drawing people
&lt;/h3&gt;

&lt;p&gt;The first palette was cool mint, which is wrong for a golgappa. I rebuilt the tokens from the stall itself: sand, tamarind, saffron, roasted brown, imli pani, fried puri.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What failed.&lt;/strong&gt; I wanted a girl at the stall, pouring pani into a golgappa and reacting to each section as you scroll. Claude hand-drew her in SVG over three passes. The face worked, the arms never did: stroked limbs with separate hand shapes leave a lump where the outlines cross. After the third try the honest call was that hand-authoring a natural human figure in raw SVG paths was not going to get good, so we stopped iterating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What worked.&lt;/strong&gt; I generated her instead. One reference image from a detailed prompt, then three more moods generated &lt;em&gt;from that image as the reference&lt;/em&gt;, changing only pose and expression, which is what kept her the same person. Backgrounds were cut out locally with &lt;code&gt;sharp&lt;/code&gt; (flood-fill from the border, clear the big white gaps in the hair, keep small ones like eye whites, recolour the feathered edge so there is no white fringe on the dark theme). About 42 KB per pose as WebP. The image tool's schema was opaque, the free plan allowed one job at a time and I ran out of credits after four images, so the fifth mood reuses a pose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scroll bug.&lt;/strong&gt; The first version used an IntersectionObserver and got silently stuck, because the figure itself carried &lt;code&gt;data-mood&lt;/code&gt; so the observer kept picking her own mood. Then the footer never triggered because it is too short to reach the middle of the screen. One check per animation frame replaced both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 3: dressing the page as an actual stall
&lt;/h3&gt;

&lt;p&gt;Feedback was that the girl was right but the page still read like a SaaS template. So it became a thela: a scalloped awning with bunting in pure CSS, a signboard headline with पानी painted huge behind it, an LED ticker reading every area's state off Sanity, a chalkboard "Aaj ka menu" with the action where the price would be and the &lt;strong&gt;Shake the golgappa&lt;/strong&gt; simulator running the real &lt;code&gt;scoreReports&lt;/code&gt; from &lt;code&gt;lib/risk.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug caught by clicking, not by reading:&lt;/strong&gt; three fast clicks on "+" counted two, because the stepper computed &lt;code&gt;value + 1&lt;/code&gt; from a stale render. Functional updates fixed it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy day
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vercel refused the first deploy: the Hobby plan only allows daily cron jobs and my &lt;code&gt;vercel.json&lt;/code&gt; ran the case tick every 15 minutes. The tick only closes quiet cases and returns recovered areas to Crisp, so daily is enough.&lt;/li&gt;
&lt;li&gt;I finally checked the IS 10500 numbers I had written from memory on Day 1. Every value was right, but two &lt;strong&gt;citations&lt;/strong&gt; were wrong (chlorine is in Table 2, bacteria in Table 6). Because limits are content, the fix was a three document patch, not a code change. That was the schema decision paying off.&lt;/li&gt;
&lt;li&gt;The hero said "Indore · live" right under a banner saying "Sample data". It now says demo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3 October: auditing the decision path
&lt;/h3&gt;

&lt;p&gt;I asked Claude to rate the project as a judge would. It gave functionality a 7, so I asked what would make it a 9.5. The answer was an audit of every path from report to alert, and it found real bugs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The App SDK control room only ever wrote drafts.&lt;/strong&gt; &lt;code&gt;@sanity/sdk&lt;/code&gt; edits the draft unless the document handle says &lt;code&gt;liveEdit: true&lt;/code&gt;. Confirming in the Dashboard made a draft alert the public site never saw. Now the decision, the alert and the area turning red go in one live-edit transaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Mark fixed" had no button,&lt;/strong&gt; so Fresh batch was unreachable from the control room.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A case could be confirmed twice,&lt;/strong&gt; which made two alerts. Decisions now act only on cases waiting for a person, every write is guarded by the case &lt;code&gt;_rev&lt;/code&gt;, and the alert id is derived from the case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server actions trusted the page.&lt;/strong&gt; Server actions are public endpoints, so each one now checks the sign-in itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A reporter's phone number was one GROQ query away&lt;/strong&gt; on a public dataset. Contact details now live in &lt;code&gt;private.contact.&amp;lt;reportId&amp;gt;&lt;/code&gt; documents. Ids with a dot sit on a path that Sanity never returns to unauthenticated requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A date filter never matched.&lt;/strong&gt; &lt;code&gt;submittedAt&lt;/code&gt; is a string, and comparing it to &lt;code&gt;dateTime(now())&lt;/code&gt; without &lt;code&gt;dateTime()&lt;/code&gt; was always false. Area pages showed no reports and the rate limit never fired. There is now a test that scans every GROQ string for that mistake.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The case rules became pure functions with tests, so "the scorer can raise a case to needs verification and never past it" is tested directly. Tests went from 11 to 29.&lt;/p&gt;

&lt;h3&gt;
  
  
  The last evening: a check from a stale copy
&lt;/h3&gt;

&lt;p&gt;On the last evening I asked a local Claude Code session "what is left". It read an old copy of the project on my Mac that had no git remote and stopped at 21 September, so its first answer was confidently wrong. The mistake surfaced when a CLI deploy from that folder was &lt;strong&gt;blocked&lt;/strong&gt; by Vercel: its commits were authored with an email the Hobby plan doesn't accept. That block saved me, because the deploy would have replaced the day's fixes with week-old code. Comparing the blocked deploy's metadata with the live one showed where the real repo was.&lt;/p&gt;

&lt;p&gt;It still found things worth fixing. &lt;code&gt;/api/cron/tick&lt;/code&gt; would run for anyone, because the secret check only ran &lt;em&gt;if&lt;/em&gt; &lt;code&gt;CRON_SECRET&lt;/code&gt; was set, and it wasn't. Now the secret is set and the route fails closed on any deployment. The citation fix had been written but never run against the live data. Two old write tokens from before the rotation were still active, and are now deleted. Then I confirmed the Sector 14 case myself in the control room and watched the area go red on the map.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I deliberately did not build
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Photo upload on reports. Asset uploads need the write token path designed properly and a reading carries more weight than a blurry photo.&lt;/li&gt;
&lt;li&gt;A Hindi interface. The &lt;em&gt;content&lt;/em&gt; is bilingual (area names, advice, alert precautions), the UI chrome is still English.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sanity Project Details
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project ID:&lt;/strong&gt; &lt;code&gt;ya4g5th1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dataset:&lt;/strong&gt; &lt;code&gt;production&lt;/code&gt; (public)&lt;/li&gt;
&lt;li&gt;Schema: &lt;code&gt;sanity/schemaTypes/&lt;/code&gt; (9 types), workflow: &lt;code&gt;sanity/workflows/waterCase.ts&lt;/code&gt;, App SDK app: &lt;code&gt;control-room/&lt;/code&gt;, scheduled Function: &lt;code&gt;functions/daily-tick/&lt;/code&gt; with &lt;code&gt;sanity.blueprint.ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>sanitychallenge</category>
      <category>sanity</category>
      <category>ai</category>
    </item>
    <item>
      <title>I built The Repair Line: turning small repairs into shared relief</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Mon, 07 Sep 2026 08:04:32 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/i-built-the-repair-line-turning-small-repairs-into-shared-relief-39bg</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/i-built-the-repair-line-turning-small-repairs-into-shared-relief-39bg</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-09-03"&gt;Weekend Challenge: Generosity Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I built &lt;strong&gt;The Repair Line&lt;/strong&gt;, a community-repair platform for the small shared things that keep a neighbourhood moving: a broken public hand pump, a leaking roof above a ration counter, a damaged study desk, or a clinic fan that has stopped working.&lt;/p&gt;

&lt;p&gt;The goal is to make generosity visible and practical. Someone uploads a clear photo of a repair need, receives an AI-assisted assessment, and can add it to a local repair line where people can see the impact, the directional cost, and the amount already pledged.&lt;/p&gt;

&lt;p&gt;Each repair includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a real repair photo and a short explanation&lt;/li&gt;
&lt;li&gt;severity, people affected, and a directional INR cost range&lt;/li&gt;
&lt;li&gt;funding progress&lt;/li&gt;
&lt;li&gt;a before-and-after proof-of-repair concept&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The experience is designed to feel warm and community-led rather than like a generic fundraising dashboard. It starts with local repairs, but the city selector supports Lucknow, Kanpur, Prayagraj, Varanasi, and an all-cities view.&lt;/p&gt;

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

&lt;p&gt;Live app: &lt;a href="https://therepairline.vercel.app" rel="noopener noreferrer"&gt;The Repair Line&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try the flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose a city from the location selector.&lt;/li&gt;
&lt;li&gt;Browse local repair needs or click &lt;strong&gt;Show all repairs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;Assess a repair&lt;/strong&gt;, upload a clear photo of a broken shared item.&lt;/li&gt;
&lt;li&gt;Receive an assessment of severity, plausibility, likely repair cost, and reasoning.&lt;/li&gt;
&lt;li&gt;Add the assessed repair to the line.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The project is built with React and Vite, with API routes prepared for Vercel Functions.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/Reet24-del/the-repair-line" rel="noopener noreferrer"&gt;github.com/Reet24-del/the-repair-line&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key pieces of the implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React interface and location-aware repair feed&lt;/li&gt;
&lt;li&gt;Gemini-backed server-side assessment endpoint&lt;/li&gt;
&lt;li&gt;Snowflake-backed repair, pledge, sort, and city-filtering queries&lt;/li&gt;
&lt;li&gt;Vercel deployment and API routes&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Starting with a small but meaningful problem
&lt;/h3&gt;

&lt;p&gt;I wanted to focus on generosity that is easy to understand. Not every community need requires a huge campaign. A ₹2,000–₹10,000 repair can make a real difference when it restores a shared tap, desk, roof, or fan.&lt;/p&gt;

&lt;p&gt;The product flow became: &lt;strong&gt;photo in, fixed out&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI assessment with Google Gemini
&lt;/h3&gt;

&lt;p&gt;The repair assessor accepts a photo and sends it to a server-side Gemini route. Gemini is asked to return structured JSON with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="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="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Low | Medium | High"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a directional INR range"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plausibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Likely genuine | Needs review | Unclear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a concise explanation"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I require a photo before an assessment can run. This prevents the interface from creating a confident-looking repair result without visual evidence. The cost is intentionally presented as directional guidance rather than a quote.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repair feed and Snowflake
&lt;/h3&gt;

&lt;p&gt;Repair records include the repair title, location, severity, estimated cost, people helped, reason, image, and pledged amount. The Snowflake schema and query layer support feed filters for city, severity, and sorting.&lt;/p&gt;

&lt;p&gt;The feed initially keeps the page focused by showing a smaller set of repairs. A &lt;strong&gt;Show all repairs&lt;/strong&gt; control expands the complete list, while the city selector changes the listings and heading to keep the experience locally relevant.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;The frontend is deployed on Vercel, while Vercel Functions host the assessment, repair, and pledge endpoints. Sensitive credentials stay in server-side environment variables rather than the browser bundle.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Best Use of Google AI
&lt;/h3&gt;

&lt;p&gt;The project uses Google Gemini to analyse an uploaded repair photo and produce a structured, user-facing assessment. Gemini helps translate a visual problem into understandable severity, plausibility, repair guidance, and an INR cost range.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Use of Snowflake
&lt;/h3&gt;

&lt;p&gt;Snowflake provides the repair data layer for listings and pledges. The app is designed to query repairs by city, severity, and priority, so a growing local repair line remains filterable and useful.&lt;/p&gt;




&lt;p&gt;The Repair Line is a small idea on purpose: make a modest, shared repair easy to see, trust, and complete.&lt;/p&gt;

</description>
      <category>community</category>
      <category>react</category>
      <category>ai</category>
    </item>
    <item>
      <title>The Answer Looked Right. That Was the Problem.</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Sun, 30 Aug 2026 16:28:44 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/the-answer-looked-right-that-was-the-problem-lhn</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/the-answer-looked-right-that-was-the-problem-lhn</guid>
      <description>&lt;p&gt;I started building &lt;strong&gt;The Verifier&lt;/strong&gt; because of a slightly uncomfortable thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if an AI gives you a perfectly written answer based on yesterday's truth?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not a hallucination. Not an obviously fake source. Just an answer that &lt;em&gt;used to be correct&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That felt more dangerous.&lt;/p&gt;

&lt;p&gt;A polished lie is easy to fear. An outdated fact wearing a confident suit? That one can quietly walk straight into reports, presentations, articles, and important decisions.&lt;/p&gt;

&lt;p&gt;So I decided to build something that would not simply answer a claim.&lt;/p&gt;

&lt;p&gt;It would argue with itself first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet The Verifier
&lt;/h2&gt;

&lt;p&gt;The Verifier is an evidence-first research assistant for public claims.&lt;/p&gt;

&lt;p&gt;You give it a claim such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Verify that Brian Niccol is the CEO of Starbucks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of immediately producing a confident paragraph, it investigates the claim from two opposing directions.&lt;/p&gt;

&lt;p&gt;One research lane looks for evidence supporting the claim. Another actively searches for credible evidence contradicting it.&lt;/p&gt;

&lt;p&gt;This matters because normal search behaviour has a bias: once we find one convincing source, we usually stop looking.&lt;/p&gt;

&lt;p&gt;The Verifier does not get that luxury.&lt;/p&gt;

&lt;p&gt;It has to search both sides, place the evidence next to each other, and show its work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then Starbucks created the perfect plot twist
&lt;/h2&gt;

&lt;p&gt;The Starbucks leadership example turned out to be a great demonstration.&lt;/p&gt;

&lt;p&gt;One public source identifies Brian Niccol as Starbucks' current chairman and CEO.&lt;/p&gt;

&lt;p&gt;Another Starbucks source names Laxman Narasimhan as CEO.&lt;/p&gt;

&lt;p&gt;Both sources are real. Both come from Starbucks. Both look authoritative.&lt;/p&gt;

&lt;p&gt;So which one should the system trust?&lt;/p&gt;

&lt;p&gt;This is where the project became more than a fancy search interface.&lt;/p&gt;

&lt;p&gt;The answer was hiding in the metadata.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dates are boring—until they solve the mystery
&lt;/h2&gt;

&lt;p&gt;Most people do not get excited about fields such as datePublished, dateModified, or ISO timestamps.&lt;/p&gt;

&lt;p&gt;Honestly, neither did I.&lt;/p&gt;

&lt;p&gt;But those tiny pieces of metadata became the detective of this story.&lt;/p&gt;

&lt;p&gt;The Verifier extracts machine-readable dates from every source. It records which metadata field was used, preserves the original value, and normalizes the date to UTC.&lt;/p&gt;

&lt;p&gt;Now the system can compare evidence deterministically.&lt;/p&gt;

&lt;p&gt;It does not choose a source because it sounds more confident. It can explain that one source represents an older leadership announcement while another contains newer evidence about the company's current leadership.&lt;/p&gt;

&lt;p&gt;That difference matters.&lt;/p&gt;

&lt;p&gt;The conclusion is not merely:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Brian Niccol is CEO.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The claim is supported by newer public evidence. The conflicting source is legitimate, but outdated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suddenly, the contradiction is not something to hide. It is part of the explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  I wanted the disagreement to remain visible
&lt;/h2&gt;

&lt;p&gt;A lot of AI tools clean up the messy middle.&lt;/p&gt;

&lt;p&gt;You provide a question. Something complicated happens. A neat answer appears.&lt;/p&gt;

&lt;p&gt;Magic.&lt;/p&gt;

&lt;p&gt;Also slightly terrifying.&lt;/p&gt;

&lt;p&gt;I wanted The Verifier to show the messy middle.&lt;/p&gt;

&lt;p&gt;The interface keeps the supporting and conflicting evidence in separate lanes. Each source displays its role, URL, relevant statement, and date information.&lt;/p&gt;

&lt;p&gt;The user can inspect why the system reached its conclusion instead of being asked to trust a glowing confidence score.&lt;/p&gt;

&lt;p&gt;Because “97% confident” sounds impressive, but it does not tell me whether the model checked last year's announcement against today's leadership page.&lt;/p&gt;

&lt;p&gt;Evidence does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The voice feature fought back
&lt;/h2&gt;

&lt;p&gt;I also wanted the experience to feel conversational.&lt;/p&gt;

&lt;p&gt;The original idea was simple: click &lt;strong&gt;Speak brief&lt;/strong&gt;, say the claim, and continue asking questions naturally.&lt;/p&gt;

&lt;p&gt;The browser had other plans.&lt;/p&gt;

&lt;p&gt;At one point, the button barely behaved like a button. Then voice mode required clicking it repeatedly. Even worse, every new interaction felt like the previous conversation had been erased from existence.&lt;/p&gt;

&lt;p&gt;The Verifier had the memory of a goldfish with Wi-Fi.&lt;/p&gt;

&lt;p&gt;That forced me to rethink the feature.&lt;/p&gt;

&lt;p&gt;Voice could not be a one-shot transcription gimmick. It needed to be a continuous conversation where the active claim, collected sources, and date resolution remained available for follow-up questions.&lt;/p&gt;

&lt;p&gt;I also added text as a permanent fallback because demos—and browsers—have a wonderful sense of dramatic timing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent can research. It cannot press Save for you.
&lt;/h2&gt;

&lt;p&gt;This became my favourite part of the project.&lt;/p&gt;

&lt;p&gt;After completing the investigation, The Verifier does not automatically store the result.&lt;/p&gt;

&lt;p&gt;It asks the user for approval.&lt;/p&gt;

&lt;p&gt;That is not just a polite message in the interface. The restriction is enforced on the server.&lt;/p&gt;

&lt;p&gt;The server creates a one-time approval token and refuses to persist the dossier until explicit approval is received. Export remains locked as well.&lt;/p&gt;

&lt;p&gt;If the user chooses to keep investigating, nothing is saved.&lt;/p&gt;

&lt;p&gt;Only after server-confirmed approval does the dossier become permanent and downloadable.&lt;/p&gt;

&lt;p&gt;The system can investigate, compare, and explain.&lt;/p&gt;

&lt;p&gt;The final decision still belongs to a human.&lt;/p&gt;

&lt;h2&gt;
  
  
  Of course, the build was not a straight line
&lt;/h2&gt;

&lt;p&gt;The first UI used fictional “Maya Chen” and “Northstar AI” evidence while the backend used the real Starbucks case.&lt;/p&gt;

&lt;p&gt;Very coherent. Absolutely no notes.&lt;/p&gt;

&lt;p&gt;That mismatch had to go.&lt;/p&gt;

&lt;p&gt;Then came GitHub authentication, voice bugs, disappearing conversational context, provider configuration, Groq setup, and a Daytona API key that continued rejecting me like it had a personal grudge.&lt;/p&gt;

&lt;p&gt;Some parts worked immediately. Several parts worked only after I stopped assuming they worked. A few parts smiled during testing and broke the moment I opened the demo.&lt;/p&gt;

&lt;p&gt;That is the real version of building for a hackathon.&lt;/p&gt;

&lt;p&gt;It is not one cinematic montage with energetic music. It is a series of tiny mysteries, questionable browser tabs, and commits that begin with the word “fix.”&lt;/p&gt;

&lt;p&gt;But each problem improved the project.&lt;/p&gt;

&lt;p&gt;The fictional demo became a real public case. The voice button became a conversation. The date field became an explanation. The approval message became a server boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  What The Verifier is really about
&lt;/h2&gt;

&lt;p&gt;The Verifier is not trying to make AI sound smarter.&lt;/p&gt;

&lt;p&gt;It is trying to make AI easier to question.&lt;/p&gt;

&lt;p&gt;The important output is not only the final conclusion. It is the path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What evidence supported the claim?&lt;/li&gt;
&lt;li&gt;What evidence contradicted it?&lt;/li&gt;
&lt;li&gt;Which source was newer?&lt;/li&gt;
&lt;li&gt;Which metadata field proved that?&lt;/li&gt;
&lt;li&gt;Why was the conflict resolved this way?&lt;/li&gt;
&lt;li&gt;Did a human approve saving the result?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That path becomes an inspectable dossier that a researcher, journalist, policy team, or compliance reviewer can defend.&lt;/p&gt;

&lt;p&gt;The internet changes. Leadership changes. Policies change. Yesterday's correct answer quietly becomes today's misinformation.&lt;/p&gt;

&lt;p&gt;The Verifier is my attempt to catch that moment.&lt;/p&gt;

&lt;p&gt;Not by asking you to trust another polished AI answer.&lt;/p&gt;

&lt;p&gt;By showing you the evidence, explaining the conflict, and waiting for you to decide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify first. Save only when you are ready.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;🚀 &lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://the-verifier.vercel.app" rel="noopener noreferrer"&gt;the-verifier.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Project:&lt;/strong&gt; &lt;a href="https://github.com/Reet24-del/the-verifier" rel="noopener noreferrer"&gt;github.com/Reet24-del/the-verifier&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you build with AI, I would love to know: &lt;strong&gt;what part of an answer do you wish AI tools showed more clearly?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>hackathon</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Good Boy Amnesia: An AI Detective Game where Memory IS the Gameplay 🐶🧠</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Mon, 17 Aug 2026 07:04:29 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/good-boy-amnesia-an-ai-detective-game-where-memory-is-the-gameplay-5ap0</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/good-boy-amnesia-an-ai-detective-game-where-memory-is-the-gameplay-5ap0</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/weekend-2026-08-13"&gt;Weekend Challenge: Dog Days Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Good Boy Amnesia&lt;/strong&gt; is a detective game built for Dog Days where an AI agent's entire long-term memory lifecycle — &lt;code&gt;remember → recall → memify → forget&lt;/code&gt; — &lt;strong&gt;is the gameplay loop&lt;/strong&gt;, visualized as a live 3D knowledge graph in Three.js.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Story:
&lt;/h3&gt;

&lt;p&gt;Your owner &lt;strong&gt;Dev&lt;/strong&gt; left you home alone last night, and you threw a legendary neighborhood puppy party. At 6:00 AM, your memory graph was corrupted. Dev arrives home at &lt;strong&gt;noon (12:00 PM)&lt;/strong&gt;, the living room is trashed, and his favorite leather slipper is missing.&lt;/p&gt;

&lt;p&gt;You play &lt;strong&gt;Buster&lt;/strong&gt;, a Golden Retriever whose mind is literally a knowledge graph. Reconstruct what happened last night, interrogate the neighborhood animals, purge false rumors, and find Dev's slipper before he walks through the door!&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo &amp;amp; Screenshots 🎮
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Game Demo&lt;/strong&gt;: &lt;code&gt;https://good-boy-amnesia.vercel.app&lt;/code&gt; &lt;em&gt;(or your Hugging Face Space URL)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video Walkthrough&lt;/strong&gt;: &lt;em&gt;(Optional link to your screen recording)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gameplay Breakdown:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;🔍 Investigate Hotspots&lt;/strong&gt;: Explore 6 locations (&lt;em&gt;Living Room, Backyard Lawn, Bella's Garden Fence, Dog Park, Lou's Oak Tree Stash, and Rooftop Sandbox&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🗂 File Clues (&lt;code&gt;remember&lt;/code&gt;)&lt;/strong&gt;: Committing a fact adds glowing nodes to your live 3D memory graph in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;💬 Interrogate Animals&lt;/strong&gt;: Chat with &lt;strong&gt;Bella&lt;/strong&gt; (the wise cat), &lt;strong&gt;Lou&lt;/strong&gt; (the shifty raccoon), &lt;strong&gt;Rev. Rex&lt;/strong&gt; (the howling Basset Hound), and &lt;strong&gt;Barnaby&lt;/strong&gt; (the hungover pug). The characters read your live graph and react dynamically to your knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🧠 Connect the Dots (&lt;code&gt;memify&lt;/code&gt;)&lt;/strong&gt;: Consolidate stored memories into derived inferences (e.g. realizing the slipper was locked in the treat safe before the party started).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🗑 Purge False Leads (&lt;code&gt;forget&lt;/code&gt;)&lt;/strong&gt;: 5 red herrings are hidden in the story. Delete gossip from your memory log to keep your graph clean and win the case!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🎯 Tell Dev (&lt;code&gt;solve&lt;/code&gt;)&lt;/strong&gt;: Reconstruct the timeline before noon to win in a burst of victory confetti!&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Code Repository ⭐
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/your-username/good-boy-amnesia" rel="noopener noreferrer"&gt;github.com/your-username/good-boy-amnesia&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How I Built It (Tech Stack) 🛠️
&lt;/h2&gt;

</description>
      <category>devchallenge</category>
      <category>ai</category>
      <category>gamedev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>From My Father's Agricultural Knowledge to a Voice AI for Farmers</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Sat, 15 Aug 2026 16:12:54 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/from-my-fathers-agricultural-knowledge-to-a-voice-ai-for-farmers-56eh</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/from-my-fathers-agricultural-knowledge-to-a-voice-ai-for-farmers-56eh</guid>
      <description>&lt;p&gt;My father has a master's degree in agriculture. Growing up around someone who had studied the subject deeply made me notice that a farming question is rarely as small as it sounds.&lt;/p&gt;

&lt;p&gt;“Which crop should I grow?” can depend on soil, season, water, location, cost, and risk. A mark on a leaf might be harmless, or it might be the first sign of a problem that needs an expert. The useful answer is not the longest answer. It is the answer that understands the situation and helps someone decide what to do next.&lt;/p&gt;

&lt;p&gt;A friend of mine made this gap feel real in a different way. He had land, money to invest, and an idea for an agriculture-related business. What he did not have was fluency in the subject. He could search online, but he did not always know which question to ask, which source to trust, or when general advice was no longer enough.&lt;/p&gt;

&lt;p&gt;My father had the knowledge. My friend had the intent and the resources. Between them was a problem of access.&lt;/p&gt;

&lt;p&gt;That problem is larger than one conversation. The Government of India's &lt;a href="https://www.pib.gov.in/Pressreleaseshare.aspx?PRID=2050966&amp;amp;lang=2&amp;amp;reg=48" rel="noopener noreferrer"&gt;Digital Agriculture Mission&lt;/a&gt; describes the need for timely, reliable information and customised advisories for crop planning, crop health, pest management, and irrigation. Data may exist in many places, but a person standing in a field still needs a simple way to reach the right information.&lt;/p&gt;

&lt;p&gt;I kept returning to one thought: what if asking for farming help could feel less like operating software and more like speaking to someone who listens?&lt;/p&gt;

&lt;p&gt;That thought became &lt;strong&gt;Kisan Sahayak&lt;/strong&gt;.&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%2Fiw4buq4xkugc20egmffi.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%2Fiw4buq4xkugc20egmffi.png" alt="Kisan Sahayak in a live Hinglish conversation with weather and saved memory" width="799" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The assistant I wanted to build
&lt;/h2&gt;

&lt;p&gt;Kisan Sahayak is a browser and phone-based voice AI assistant for Indian farmers and people beginning an agricultural venture. A user can speak in English, Hindi, or Hinglish and ask about crops, soil, irrigation, local weather, or an emerging crop problem.&lt;/p&gt;

&lt;p&gt;The assistant can fetch live data, remember useful details with permission, place a controlled advisory call, create a human-help request, measure whether a conversation achieved its purpose, and transfer crop symptoms to a separate specialist agent.&lt;/p&gt;

&lt;p&gt;It is not meant to replace an agronomist. Its job is to shorten the distance between a spoken question and a safe next step. When it does not have reliable data, it should say so. When a case needs a specialist or a person, it should stop pretending to be enough.&lt;/p&gt;

&lt;p&gt;I built it during &lt;strong&gt;10 Days of Voice Agents — VoiceForBharat Edition&lt;/strong&gt;. Its speech is powered by &lt;strong&gt;Murf Falcon&lt;/strong&gt;. Murf describes Falcon 2 as a real-time speech model with roughly 100 ms time-to-first-audio and the ability to switch languages within a sentence, both of which matter in a conversation that may move naturally between Hindi and English. You can read the technical details in the &lt;a href="https://murf.ai/api/docs/text-to-speech-models/falcon-2" rel="noopener noreferrer"&gt;Falcon 2 documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The source code is available here: &lt;a href="https://github.com/Reet24-del/murf-livekit-starter" rel="noopener noreferrer"&gt;github.com/Reet24-del/murf-livekit-starter&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when a farmer speaks
&lt;/h2&gt;

&lt;p&gt;A voice assistant sounds like one system, but it is a chain of systems working quickly enough to feel like one conversation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deepgram Nova-3&lt;/strong&gt; converts speech into text. The project uses multilingual recognition so the caller can speak English, Hindi, or a mixture of both. Deepgram documents its supported models and languages in its &lt;a href="https://developers.deepgram.com/docs/models-languages-overview" rel="noopener noreferrer"&gt;model overview&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Gemini&lt;/strong&gt; reads the latest request, conversation context, safety instructions, and available tools. It decides whether to answer, fetch data, ask for consent, or transfer control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Murf Falcon&lt;/strong&gt; converts the reply into speech. The main assistant uses the Anisha voice. The crop specialist uses Samar, so the caller can hear that a real handoff has happened.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LiveKit&lt;/strong&gt; carries the audio and manages the real-time agent session between the browser or phone and the Python backend. Its documentation describes the same sequential &lt;a href="https://docs.livekit.io/agents/models/pipelines/" rel="noopener noreferrer"&gt;STT–LLM–TTS pipeline&lt;/a&gt; used in this project.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Farmer speaks
     |
     v
LiveKit room
     |
     v
Deepgram STT ---&amp;gt; latest-turn language detection
     |                         |
     v                         v
Google Gemini &amp;lt;--- memory, tools, consent, safety rules
     |
     +---- routine question ----&amp;gt; Kisan Sahayak
     |
     +---- crop symptoms -------&amp;gt; Crop Problem Specialist
     |
     v
Murf Falcon TTS
     |
     v
The farmer hears the answer

Supporting services:
Open-Meteo -&amp;gt; live district weather
SQLite     -&amp;gt; consented memory, help requests, and call outcomes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture gave me a useful separation of responsibilities. The language model handles conversation. Tools handle facts that can change. SQLite handles information that must survive after a call. The specialist handles a narrower class of problems. The frontend tells the user what the system is doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ten days, one layer at a time
&lt;/h2&gt;

&lt;p&gt;The project did not begin with all of these abilities. Each daily task exposed a weakness in the version from the day before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 1: Giving the idea a voice
&lt;/h3&gt;

&lt;p&gt;The first version had one goal: complete a live voice loop.&lt;/p&gt;

&lt;p&gt;I connected Deepgram speech-to-text, Gemini, Murf Falcon text-to-speech, and LiveKit transport. For the first time, I could speak into the browser and hear the assistant answer. During my local tests, the observed time-to-first-audio ranged from 137 ms to 263 ms. Those numbers are local observations, not a universal benchmark, because network, region, model, and device all affect perceived latency.&lt;/p&gt;

&lt;p&gt;The early success was exciting, but it also revealed a truth about voice products. A correct answer can still feel wrong if the pause before it is too long. Latency is part of the conversation design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 2: Deciding who the agent should be
&lt;/h3&gt;

&lt;p&gt;A working voice loop is not yet an assistant. On Day 2, I gave Kisan Sahayak a clear role, tone, and boundary.&lt;/p&gt;

&lt;p&gt;It would answer only farming and local-weather questions. It would keep spoken replies short. It would never invent current market prices, subsidy details, pesticide doses, or long-range weather. Hindi replies would use Devanagari. English replies would remain English. Hinglish could stay in Roman script.&lt;/p&gt;

&lt;p&gt;I also tested hostile and out-of-scope prompts. This was where the project moved from “Can it answer?” to “Can it answer responsibly?” The biggest lesson was that refusal behavior must be designed with as much care as the happy path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 3: Making the invisible conversation visible
&lt;/h3&gt;

&lt;p&gt;Voice interfaces can be confusing when the screen gives no feedback. Is the microphone active? Is the agent thinking? Has the session ended?&lt;/p&gt;

&lt;p&gt;I built a browser interface that shows clear states: ready, connecting, listening, thinking, speaking, transferring, and ended. I added a live transcript, a weather panel, saved memory, and controls that avoid ending a call through an accidental tap.&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%2Frqohn0r5p7e8myeuz1az.jpg" 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%2Frqohn0r5p7e8myeuz1az.jpg" alt="Kisan Sahayak voice portal showing the voice orb, live weather panel, saved memory, and call controls" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The interface uses a dark field-inspired visual language, but its main purpose is practical. A user should never have to guess whether the assistant heard them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 4: Building memory without taking ownership of the user's data
&lt;/h3&gt;

&lt;p&gt;The assistant could remember a conversation while the session was open, then forget everything when the user returned. Day 4 added persistent memory through SQLite.&lt;/p&gt;

&lt;p&gt;Kisan Sahayak can save a caller's name, district, crops, land size, irrigation type, preferred language, and a short summary. It saves new information only after permission. A direct instruction such as “Remember that my district is Lucknow” also counts as clear permission.&lt;/p&gt;

&lt;p&gt;This distinction became important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conversation context helps during the current call.&lt;/li&gt;
&lt;li&gt;Stored memory helps during a future call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The database stores selected facts, not the full conversation. Python's &lt;a href="https://docs.python.org/3/library/sqlite3.html" rel="noopener noreferrer"&gt;&lt;code&gt;sqlite3&lt;/code&gt; documentation&lt;/a&gt; describes SQLite as a lightweight disk-based database that does not require a separate server, which made it a good fit for a local challenge build. A deployed version would need encryption, authentication, retention rules, and stronger access controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 5: Teaching the assistant to use real data
&lt;/h3&gt;

&lt;p&gt;The model once gave the wrong current time. That failure made the next design decision obvious: anything described as “current” must come from a current source.&lt;/p&gt;

&lt;p&gt;I added a function tool that fetches district weather from Open-Meteo and another that reads the system clock in the Asia/Kolkata timezone. The weather result includes its source time, current conditions, wind, temperature range, and rain probability. Open-Meteo documents the available current and forecast variables in its &lt;a href="https://open-meteo.com/en/docs" rel="noopener noreferrer"&gt;Weather Forecast API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The failure path mattered as much as the successful response. The weather request has a timeout. If the service is down or returns incomplete data, the assistant says that live weather is unavailable and refuses to guess.&lt;/p&gt;

&lt;p&gt;The tool description also mattered. The model decides whether to call a function from that description, so “use this for current weather, rain chance, temperature, wind, spraying, irrigation, sowing, or harvesting” produced better routing than a vague label such as “weather tool.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 6: Moving from browser conversations to outbound calls
&lt;/h3&gt;

&lt;p&gt;Some useful information should reach a farmer before they open a website. On Day 6, I added controlled outbound rain-advisory calls through LiveKit SIP, with Linphone or Twilio as the call provider.&lt;/p&gt;

&lt;p&gt;This feature includes rules that are easy to overlook in a demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the recipient must have consented;&lt;/li&gt;
&lt;li&gt;the destination must be valid;&lt;/li&gt;
&lt;li&gt;calls are limited to 08:00–20:00 IST;&lt;/li&gt;
&lt;li&gt;saved opt-outs are honoured;&lt;/li&gt;
&lt;li&gt;the weather tool must run before a current advisory is spoken;&lt;/li&gt;
&lt;li&gt;failed, unanswered, or declined calls receive a controlled outcome.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hard part was not writing a dial command. It was connecting the SIP trunk, worker registration, dispatch rule, verified destination, and agent name without mixing credentials between services. Telephony made every configuration mismatch visible immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 7: Knowing when to ask a human
&lt;/h3&gt;

&lt;p&gt;An AI assistant should not stretch every problem until it sounds solvable. I selected two situations for human help: serious or rapidly spreading crop damage, and market information that is missing or stale.&lt;/p&gt;

&lt;p&gt;The assistant first says what it plans to share: who needs help, what happened, what it checked, urgency, language, and the requested follow-up method. It then asks for a clear yes or no. If the caller declines, no request is created.&lt;/p&gt;

&lt;p&gt;After consent, the system stores a short redacted summary and returns a reference ID. It does not store passwords, OTPs, PINs, account numbers, or a full transcript.&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%2F893y0f4bdxrpz4aobj66.jpg" 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%2F893y0f4bdxrpz4aobj66.jpg" alt="Human help request dashboard showing reference ID, urgency, language, status, summary, checks, and follow-up method" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This day changed my understanding of escalation. “Contact an expert” is advice. A consented request with a reference ID and visible status is a workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 8: Measuring whether a call helped
&lt;/h3&gt;

&lt;p&gt;Before Day 8, I could see calls happen but could not answer a basic product question: did the conversation achieve anything?&lt;/p&gt;

&lt;p&gt;I defined success for Kisan Sahayak as one of four outcomes: farming guidance delivered, live weather delivered, an expert request created, or an outbound rain advisory delivered. A call that ends before one of those conditions is recorded as failed even when the software did not crash.&lt;/p&gt;

&lt;p&gt;The analytics dashboard reads real browser and SIP session records from SQLite. It shows total, successful, and failed calls, along with filters, trends, channels, languages, durations, and controlled failure categories. It stores no caller identity and no transcript.&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%2Fg96nec6doc7ya0yvtvp3.jpg" 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%2Fg96nec6doc7ya0yvtvp3.jpg" alt="Call analytics dashboard showing successful, total, and failed calls from real sessions" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This feature forced me to separate technical reliability from user success. A perfectly stable call in which the user leaves before receiving guidance is still a failed product outcome.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 9: Handing crop problems to a specialist agent
&lt;/h3&gt;

&lt;p&gt;The main assistant had accumulated weather, memory, time, safety, escalation, and general farming responsibilities. Crop symptom triage needed a narrower role.&lt;/p&gt;

&lt;p&gt;I created a separate &lt;strong&gt;Crop Problem Specialist&lt;/strong&gt;. Reports of leaf spots, curling, wilting, pests, disease, nutrient deficiency, or unexplained crop damage trigger the handoff. The main assistant announces the transfer. The website displays “Connecting you to the specialist.” The specialist then introduces itself in a different Murf voice and continues with a copy of the existing conversation, so the farmer does not have to repeat the problem.&lt;/p&gt;

&lt;p&gt;The specialist asks one focused question at a time, offers only low-risk first steps, and never claims a certain diagnosis from a voice description. LiveKit's &lt;a href="https://docs.livekit.io/agents/logic/agents-handoffs/" rel="noopener noreferrer"&gt;agents and handoffs guide&lt;/a&gt; supports this pattern by allowing a tool call to return another agent while preserving conversation context.&lt;/p&gt;

&lt;p&gt;The first version did not route correctly. Crop symptoms competed with the older human-escalation tool, so the assistant sometimes offered a human request instead of transferring the call. I fixed that by giving specialist-eligible turns deterministic priority and temporarily removing the escalation tool from that turn.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day 10: Turning the build into something another person can use
&lt;/h3&gt;

&lt;p&gt;The final day was not another agent feature. It was the work of explaining the system honestly.&lt;/p&gt;

&lt;p&gt;I organised the repository, documented setup, checked that secrets and local caller data were excluded, added screenshots, and wrote down the failures that shaped the design. A public project is more useful when a reader can understand its limits, run it, and reproduce the important tests.&lt;/p&gt;

&lt;p&gt;The ten-day sequence also made the product progression clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Conversation
   -&amp;gt; character and guardrails
   -&amp;gt; visible interface
   -&amp;gt; consented memory
   -&amp;gt; live tools
   -&amp;gt; outbound reach
   -&amp;gt; human help
   -&amp;gt; measurable outcomes
   -&amp;gt; specialist handoff
   -&amp;gt; documented, reproducible project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The bugs that changed the design
&lt;/h2&gt;

&lt;p&gt;The useful lessons came from moments when the assistant behaved confidently but incorrectly.&lt;/p&gt;

&lt;h3&gt;
  
  
  English questions received Hindi answers
&lt;/h3&gt;

&lt;p&gt;The original prompt described a bilingual assistant, but the bilingual greeting and earlier context sometimes outweighed the caller's newest sentence. An English question could receive a Hindi answer.&lt;/p&gt;

&lt;p&gt;I moved language detection to every completed user turn. The latest turn now decides the response mode: English, Devanagari Hindi, or Roman-script Hinglish. Tests cover all three instead of checking only the opening greeting.&lt;/p&gt;

&lt;p&gt;The fix taught me that language is not a profile setting. In a multilingual conversation, it is live session state.&lt;/p&gt;

&lt;h3&gt;
  
  
  The assistant sounded current without having current access
&lt;/h3&gt;

&lt;p&gt;Knowing that a user is in India does not give a language model access to India's current clock. General weather knowledge is not today's weather either.&lt;/p&gt;

&lt;p&gt;Time and weather now sit behind tools. Each returned value carries a time or timezone, and each failure has a spoken fallback. This removed the most dangerous kind of voice-agent error: a made-up answer delivered with a natural voice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The call ended while the user was still trying to speak
&lt;/h3&gt;

&lt;p&gt;Voice activity detection, turn detection, browser audio, silence timeouts, and session lifecycle all interact. In early runs, silence handling could mark the user away too quickly or the browser could disconnect before the final analytics record was written.&lt;/p&gt;

&lt;p&gt;I increased the away timeout, avoided automatic disconnect on silence, added controlled re-prompts, and finalised analytics through the session shutdown path. The lesson was practical: real-time state bugs rarely belong to one layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The specialist and human-help paths collided
&lt;/h3&gt;

&lt;p&gt;Both features dealt with difficult crop problems, but they served different purposes. The specialist continues the AI conversation. Human escalation creates a request after consent. Without an ownership rule, the model could choose either.&lt;/p&gt;

&lt;p&gt;The final routing order is explicit. A crop symptom goes to the specialist first. Serious cases can later move to a human-help request, but only after the specialist path and only with permission.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to run Kisan Sahayak
&lt;/h2&gt;

&lt;p&gt;You will need Python 3.10–3.14, Node.js 20 or newer, &lt;code&gt;uv&lt;/code&gt;, pnpm 9 or newer, a LiveKit Cloud project, and API keys for Murf, Deepgram, and Google AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clone and install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Reet24-del/murf-livekit-starter.git
&lt;span class="nb"&gt;cd &lt;/span&gt;murf-livekit-starter

&lt;span class="nb"&gt;cd &lt;/span&gt;backend
uv &lt;span class="nb"&gt;sync
&lt;/span&gt;uv run python src/agent.py download-files

&lt;span class="nb"&gt;cd&lt;/span&gt; ../frontend
pnpm &lt;span class="nb"&gt;install
cd&lt;/span&gt; ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Create private environment files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;backend/.env.example backend/.env.local
&lt;span class="nb"&gt;cp &lt;/span&gt;frontend/.env.example frontend/.env.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following values to &lt;code&gt;backend/.env.local&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LIVEKIT_URL=
LIVEKIT_API_KEY=
LIVEKIT_API_SECRET=
MURF_API_KEY=
DEEPGRAM_API_KEY=
GOOGLE_API_KEY=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend needs the same LiveKit project and the explicit agent name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LIVEKIT_URL=
LIVEKIT_API_KEY=
LIVEKIT_API_SECRET=
AGENT_NAME=kisan-sahayak-primary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;.env.local&lt;/code&gt; files are ignored by Git. Never publish API keys, SIP trunk IDs, phone numbers, caller records, or &lt;code&gt;backend/memory.db&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Start the application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x start_app.sh
./start_app.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:3001" rel="noopener noreferrer"&gt;http://localhost:3001&lt;/a&gt;, select &lt;strong&gt;Start Call&lt;/strong&gt;, and allow microphone access. The frontend and backend must use the same LiveKit project and agent name.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Test the two agent routes
&lt;/h3&gt;

&lt;p&gt;Ask a routine question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is today's rain chance in Lucknow?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main assistant should call the live weather tool and answer in English.&lt;/p&gt;

&lt;p&gt;Then begin another call and report a crop symptom:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My tomato leaves have black spots and are curling.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main assistant should announce a transfer. The interface should display the specialist connection state, and the crop specialist should continue without asking you to repeat the symptom.&lt;/p&gt;

&lt;p&gt;End the calls and open &lt;a href="http://localhost:3001/call-analytics" rel="noopener noreferrer"&gt;http://localhost:3001/call-analytics&lt;/a&gt;. The total should increase, and each call should be classified from its real outcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Kisan Sahayak could change, and what comes next
&lt;/h2&gt;

&lt;p&gt;My friend's original difficulty was not a lack of ideas. It was the gap between an idea and informed action. Kisan Sahayak reduces that gap in a few specific ways.&lt;/p&gt;

&lt;p&gt;It lets someone begin with the words they already know. It remembers location and crop details after consent, so a returning user does not start from zero. It brings live weather into the same conversation as crop planning. It recognises when a problem belongs to a specialist. It also leaves a visible trail when a human request is created or a call fails to reach its goal.&lt;/p&gt;

&lt;p&gt;The current version remains a prototype. Its crop guidance should be strengthened with an agronomist-reviewed knowledge base. District-level mandi prices need a dependable live source and clear timestamps. Photo-assisted crop triage could add evidence that voice alone cannot provide. The local SQLite database should move to encrypted hosted storage with authentication and role-based access before public deployment. Finally, field testing across different accents, devices, and network conditions should shape the next round of changes.&lt;/p&gt;

&lt;p&gt;My father’s education reminds me how much context sits behind a reliable agricultural answer. My friend’s plan reminds me how difficult that context can be to reach when someone is starting out. Kisan Sahayak is my attempt to make the first step easier while preserving the point at which software should call a specialist or ask a person for help.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pib.gov.in/Pressreleaseshare.aspx?PRID=2050966&amp;amp;lang=2&amp;amp;reg=48" rel="noopener noreferrer"&gt;Digital Agriculture Mission, Press Information Bureau, Government of India&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://murf.ai/api/docs/text-to-speech-models/falcon-2" rel="noopener noreferrer"&gt;Murf Falcon 2 documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.livekit.io/agents/models/pipelines/" rel="noopener noreferrer"&gt;LiveKit voice pipeline types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.livekit.io/agents/logic/agents-handoffs/" rel="noopener noreferrer"&gt;LiveKit agents and handoffs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.deepgram.com/docs/models-languages-overview" rel="noopener noreferrer"&gt;Deepgram models and languages overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://open-meteo.com/en/docs" rel="noopener noreferrer"&gt;Open-Meteo Weather Forecast API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/sqlite3.html" rel="noopener noreferrer"&gt;Python &lt;code&gt;sqlite3&lt;/code&gt; documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Reet24-del/murf-livekit-starter" rel="noopener noreferrer"&gt;Kisan Sahayak source code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>voiceai</category>
      <category>ai</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Last Light: The Demon Lord Awaits at Dawn</title>
      <dc:creator>Reet Singh</dc:creator>
      <pubDate>Fri, 19 Jun 2026 17:32:23 +0000</pubDate>
      <link>https://dev.to/reet_singh_ee97da2986538e/last-light-the-demon-lord-awaits-at-dawn-44ob</link>
      <guid>https://dev.to/reet_singh_ee97da2986538e/last-light-the-demon-lord-awaits-at-dawn-44ob</guid>
      <description>&lt;p&gt;Last Light is an intense, top-down survival arena shooter inspired by Alice in Borderland. The game is deeply tied to the Solstice theme of Light vs. Darkness and the passage of time.&lt;/p&gt;

&lt;p&gt;As a lone samurai, you are trapped in a 12-hour cycle (from 18:00 to 06:00). Your weapon is a "Spirit Slash" that relies entirely on Solar Energy. To survive the encroaching dark and the endless hordes of demons, you must constantly seek out golden "Sanctuaries" to recharge your light.&lt;/p&gt;

&lt;p&gt;As the hours tick by, the darkness grows stronger, and the arena itself evolves against you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;21:00 (The Walls Rise): Massive cursed barriers emerge, forcing you into a maze.&lt;/li&gt;
&lt;li&gt;00:00 (Midnight): Lethal, rotating lasers ignite across the arena.&lt;/li&gt;
&lt;li&gt;03:00 (Spirit Fading): The safe sanctuaries detach and begin moving erratically.&lt;/li&gt;
&lt;li&gt;05:00 (The Demon Lord): The final shadow descends.
The goal was to create a high-stakes, fast-paced game where the environment is just as deadly as the enemies, perfectly capturing the feeling of fighting through the longest, darkest night of the year to finally see the sun rise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Video Demo&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/My0KjRLO1YM"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Code&lt;br&gt;
&lt;/p&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/Reet24-del" rel="noopener noreferrer"&gt;
        Reet24-del
      &lt;/a&gt; / &lt;a href="https://github.com/Reet24-del/last-light" rel="noopener noreferrer"&gt;
        last-light
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &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;Last Light: A June Solstice Survival Arena&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Last Light&lt;/strong&gt; is an intense, top-down survival arena shooter built for the June Solstice Game Jam. It features dynamic mechanics inspired by &lt;em&gt;Alice in Borderland&lt;/em&gt;, where the arena itself evolves to become your greatest enemy as the hours pass.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The Theme: Light, Darkness, and the Solstice&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;As the June Solstice arrives, the game explores the balance between light and darkness. You must constantly seek the golden "Light Zones" to recharge your solar weapon while fending off creatures of the dark. As the 12-hour cycle progresses, the darkness encroaches, and the arena becomes progressively more hostile.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The Mechanics&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solar Weaponry:&lt;/strong&gt; Your weapon drains Solar Energy instead of ammo. You must stand in golden light zones to recharge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Map Evolution:&lt;/strong&gt; Over the course of 12 hours (waves), the arena evolves
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;09:00:&lt;/strong&gt; Massive neon walls rise from the ground, creating an impenetrable maze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;12:00:&lt;/strong&gt; Lethal…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Reet24-del/last-light" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;How I Built It&lt;br&gt;
I built the game entirely from scratch using React and HTML5 Canvas, with Vite as the build tool.&lt;/p&gt;

&lt;p&gt;Technical Highlights:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Custom Game Engine: Instead of using a heavy game framework like Phaser or Unity, I built a pure requestAnimationFrame loop inside a React useEffect. React handles the state management, HUD, and overlays (like the Turing minigame), while the Canvas API handles rendering thousands of particles, enemies, and complex hitboxes at 60 FPS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Map Evolution: I implemented dynamic rectCircleCollision and lineCircleCollision algorithms. This allowed me to spawn solid maze walls mid-game that block both player movement and enemy pathing, as well as sweeping lasers that deal precise damage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Twin-Stick Mobile Support: I wrote native Multi-Touch event listeners (touchstart, touchmove, touchend) to intercept mobile interactions. Dragging on the left half of the screen creates a dynamic virtual joystick for movement, while dragging on the right controls the samurai's slash angle. The canvas scales responsively to any viewport using CSS object-fit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Prize Categories&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I am submitting Last Light for the following bonus categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Best Google AI Usage: The hyper-realistic, dark futuristic arena background (the neon-lit floor grid) was generated entirely using Google's Imagen AI models. This gave the game a premium, Alice in Borderland visual aesthetic that perfectly matched the "Darkness" theme.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Best Ode to Alan Turing: In honor of Alan Turing's legendary code-breaking legacy at Bletchley Park, the game features a Spades-style decryption minigame during pivotal hours. Time completely freezes, and a "TURING DECRYPTION REQUIRED" overlay appears. Players must read an 8-bit binary tape and decrypt it into the correct decimal number before the demons consume them. This directly honors his contributions to algorithms and modern computing by making code-breaking a literal survival mechanic!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devchallenge</category>
      <category>gamechallenge</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
