<?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: Aniruddha Shirke</title>
    <description>The latest articles on DEV Community by Aniruddha Shirke (@aniruddha_shirke_10).</description>
    <link>https://dev.to/aniruddha_shirke_10</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%2F4160352%2F13f70080-3476-4405-a772-49ad487df8ed.png</url>
      <title>DEV Community: Aniruddha Shirke</title>
      <link>https://dev.to/aniruddha_shirke_10</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aniruddha_shirke_10"/>
    <language>en</language>
    <item>
      <title>SlothDesk: A Local-First AI Assistant for Digital Chores</title>
      <dc:creator>Aniruddha Shirke</dc:creator>
      <pubDate>Sun, 25 Oct 2026 17:29:40 +0000</pubDate>
      <link>https://dev.to/aniruddha_shirke_10/slothdesk-a-local-first-ai-assistant-for-digital-chores-242p</link>
      <guid>https://dev.to/aniruddha_shirke_10/slothdesk-a-local-first-ai-assistant-for-digital-chores-242p</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;SlothDesk is a local-first assistant for small digital chores. It organizes a folder into useful categories, summarizes text-based documents, and turns pasted notes into checklists or practical plans.&lt;/p&gt;

&lt;p&gt;For file cleanup, SlothDesk scans a selected folder and prepares a preview showing each file’s suggested category and destination. Nothing moves until the user reviews the plan and confirms. It avoids overwriting existing files and keeps an undo manifest for the latest organization run.&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%2Fn39dhkfgc57lowwqllex.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%2Fn39dhkfgc57lowwqllex.png" alt="SlothDesk’s dark interface shows Gemma 3 4B ready, with a 705-file organization plan prepared for review. The plan lists suggested folders and destinations before any files are moved" width="800" height="450"&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%2Fbmfox2ioujehfto88vgs.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%2Fbmfox2ioujehfto88vgs.png" alt="The file preview lists names, suggested categories, destinations, and classification reasons. The user can review the plan and confirm or discard it before moving files." width="800" height="450"&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%2Fg6fx50fc9m7b281ui1w9.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%2Fg6fx50fc9m7b281ui1w9.png" alt="The document summary screen has a PDF selected. A side panel shows the active local Gemma model, accepted file types, and upload size limit." width="800" height="450"&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%2Fv3glgudejj41mjc1j7a4.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%2Fv3glgudejj41mjc1j7a4.png" alt="The generated summary continues with model results, an energy-prediction note, and the project conclusion." width="800" height="450"&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%2Fwdpxamyjiwjsit8hdexq.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%2Fwdpxamyjiwjsit8hdexq.png" alt="The About tab describes SlothDesk’s file organization, document summary, local AI helper, undo support, and current limitations." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Aniruddhashirke" rel="noopener noreferrer"&gt;
        Aniruddhashirke
      &lt;/a&gt; / &lt;a href="https://github.com/Aniruddhashirke/SlothDesk" rel="noopener noreferrer"&gt;
        SlothDesk
      &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;🦥 SlothDesk&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Your local-first AI helper for boring digital chores.&lt;/p&gt;
&lt;p&gt;SlothDesk is a Streamlit app that organizes files, summarizes text-based documents, and turns pasted notes into practical checklists. AI features use a local &lt;a href="https://ollama.com/" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt; model, so your document contents are not intentionally sent to a hosted model API.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Preview-first file organization&lt;/strong&gt; — sort files into folders by type and review every proposed move before anything changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional local AI classification&lt;/strong&gt; — ask Ollama to classify files with unknown extensions using the filename only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document summaries&lt;/strong&gt; — summarize text-based PDF, TXT, and Markdown files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI productivity helper&lt;/strong&gt; — turn pasted notes or instructions into concise plans, checklists, and summaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Undo support&lt;/strong&gt; — save a manifest for the latest organization run and restore moved files where possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy-first workflow&lt;/strong&gt; — file operations stay on your computer and Ollama runs locally.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architecture&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Main flow:&lt;/strong&gt; &lt;code&gt;Streamlit UI (app.py) -&amp;gt; Application services (src/) -&amp;gt;&lt;/code&gt;…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Aniruddhashirke/SlothDesk" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;SlothDesk is a Python and Streamlit app. File categories are assigned with extension rules first; optional AI classification is used only for unknown file types and sends the filename, not the file contents.&lt;/p&gt;

&lt;p&gt;For document summaries and the notes helper, SlothDesk sends extracted text to a local Ollama service using Gemma 3 4B. PDF text extraction uses pypdf. The main flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Folder → scan and classify → preview plan → user confirms → move files → save undo manifest
PDF/TXT/Markdown → extract text → local Gemma through Ollama → summary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Keeping File Cleanup Safe
&lt;/h2&gt;

&lt;p&gt;SlothDesk separates planning from action. First it scans the selected folder and creates a destination for each file. The preview shows the filename, suggested category, destination, and reason. I can review the plan before confirming any moves.&lt;/p&gt;

&lt;p&gt;The organizer skips hidden files, avoids overwriting existing files, and records the latest run so it can attempt to undo those moves. This makes the workflow useful for real folders where I want automation but still need control over what changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Gemma Fits
&lt;/h2&gt;

&lt;p&gt;Most files are sorted with built-in extension rules, which keeps routine classification fast and predictable. If I enable AI classification, Gemma is only asked to classify unknown file types using the filename; it does not receive those files’ contents.&lt;/p&gt;

&lt;p&gt;For document summaries and the notes helper, SlothDesk sends extracted text to Gemma through my local Ollama service. That keeps inference on my machine, while letting me choose a different installed model if I want to change the setup.&lt;/p&gt;

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

&lt;p&gt;Local inference makes privacy easier to reason about, but response time depends on the machine and whether the model is already loaded. While trying a real PDF, I hit the app’s original two-minute request timeout. I raised the timeout and improved the message shown if a request still takes too long.&lt;/p&gt;

&lt;p&gt;I haven’t measured a specific number of minutes saved, so I’m focusing on the practical reduction in steps: scan, review one plan, and confirm instead of sorting each file manually.&lt;/p&gt;

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

&lt;p&gt;Running an open-weight model locally keeps document text on the user’s computer instead of sending it to a hosted model API. Once Ollama and the model are installed, the AI features can run against the local service without depending on a cloud inference provider. The model setting is configurable, and the project code can be inspected and changed.&lt;/p&gt;

&lt;p&gt;Open tools also let people adapt the workflow to their own folders and privacy needs, rather than handing their files to a closed service just to sort or summarize them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;A folder that would take repeated manual sorting can be scanned into one reviewable plan. I can check the proposed destinations once, confirm the moves, and use the saved manifest to undo the latest run if needed. I haven’t measured a time-saving figure yet, so I’m describing the reduced steps rather than claiming a number.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>🛡️ Dispute Defender: a local AI that has to cite its evidence</title>
      <dc:creator>Aniruddha Shirke</dc:creator>
      <pubDate>Sun, 18 Oct 2026 18:35:25 +0000</pubDate>
      <link>https://dev.to/aniruddha_shirke_10/dispute-defender-a-local-ai-that-has-to-cite-its-evidence-1049</link>
      <guid>https://dev.to/aniruddha_shirke_10/dispute-defender-a-local-ai-that-has-to-cite-its-evidence-1049</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;A buyer opens a dispute on a $29 set of linen kitchen towels: "The box was crushed and the item inside is damaged." You packed it in a double-walled box with bubble wrap. USPS shows it delivered four days after it shipped. The platform gives you until the end of the month to answer.&lt;/p&gt;

&lt;p&gt;Now you have to dig up the order, the tracking, the message thread and the policy, and write something calm. It's late, and the whole thing is worth $29. Plenty of people just refund it.&lt;/p&gt;

&lt;p&gt;I made this case up. It's &lt;code&gt;case_002&lt;/code&gt; in my test set, and every case in this project is synthetic. It is the shape of problem I wanted to attack: the evidence is scattered, the deadline is short, and the amount is too small to feel worth the effort. That is my premise, not a statistic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dispute Defender&lt;/strong&gt; is a local AI that drafts the seller's reply, and &lt;strong&gt;every clause has to cite numbered evidence&lt;/strong&gt;. You give it a case folder (dispute notice, order CSV, messages, photos). It gives back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;numbered evidence (E1, E2, ...) and a list of what's missing,&lt;/li&gt;
&lt;li&gt;a fight-or-fold verdict (for case_002: FIGHT, score 0.45, expected recovery $13.05, from a simple heuristic of mine, not a calibrated probability),&lt;/li&gt;
&lt;li&gt;a letter where every clause ends in a citation like [E5],&lt;/li&gt;
&lt;li&gt;a REPAIRS list of anything the code had to change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Who would pay?&lt;/strong&gt; The person I built it for is a small marketplace seller who handles disputes alone, in the gaps between other work. I haven't asked anyone whether they'd pay, so I'm not putting a price on it. [Optional: your price idea, labeled untested.]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order 9814174 for Linen kitchen towel set ($29.00) was placed on 2026-01-13. [E2]
The carrier shows the package delivered on 2026-01-18. [E4]
On 2026-01-23, the buyer wrote: "The box was crushed and the item inside is broken." [E5]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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/Aniruddhashirke" rel="noopener noreferrer"&gt;
        Aniruddhashirke
      &lt;/a&gt; / &lt;a href="https://github.com/Aniruddhashirke/disputedefender" rel="noopener noreferrer"&gt;
        disputedefender
      &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;Dispute Defender&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A local AI that drafts a seller's reply to a marketplace dispute, where &lt;strong&gt;every clause must cite numbered evidence&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A buyer says the item never arrived, was not as described, or arrived damaged. The seller has a short deadline, the
facts are scattered across an order record, tracking, a message thread and a policy, and the amount is often too small
to feel worth the effort. Dispute Defender builds the evidence list, drafts the letter with a local Gemma model, then
checks each clause against only the evidence it cites. Code repairs what it can &lt;strong&gt;without adding a word&lt;/strong&gt; and drops
the rest.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Model: &lt;strong&gt;Gemma 3 4B&lt;/strong&gt;, open-weight, running locally through Ollama. Customer data stays on the seller's machine.&lt;/li&gt;
&lt;li&gt;Code: Python 3.10+, &lt;strong&gt;standard library only&lt;/strong&gt; (nothing to install).&lt;/li&gt;
&lt;li&gt;Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 2 ("Side Hustle"). The project and this repository
were…&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/Aniruddhashirke/disputedefender" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Python standard library only (nothing to install), 163 tests, MIT license. The README has the commands to reproduce every number below.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;The open-source AI:&lt;/strong&gt; Gemma 3 4B, an open-weight model, running locally through Ollama. The project is built around one rule: a language model never decides what counts as true.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;case folder -&amp;gt; numbered evidence -&amp;gt; triage -&amp;gt; Gemma drafts -&amp;gt; verify each clause -&amp;gt; retry once -&amp;gt; repair or drop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each clause must cite numbered evidence. A verifier checks each clause against only the evidence it cites. Code then repairs what it can without adding a word, and drops the rest. Everything after the model is plain, deterministic code.&lt;/p&gt;

&lt;p&gt;That rule caught real failures:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It described photos it never saw.&lt;/strong&gt; My photo evidence is only a file name. Gemma wrote that the photo "shows the scarf packed in its original condition," and kept doing it. A stricter prompt cut photo claims from 7 of 15 runs to 1, but it created new failures (evidence ids in prose, uncited lines) and made the model slower. So I took the decision away from the model. Code now writes the photo sentences and the model never sees them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It cited a true fact to the wrong evidence item.&lt;/strong&gt; In one case, all 3 runs wrote "Tracking shows it was delivered on April 22 [E6]." The fact is in E7. The repair added E7 without adding a word. In another case, the verifier dropped "The buyer opened a dispute on 2026-06-06 [E6]." That date appears in two evidence items, and the repair only re-cites when exactly one other item contains the fact. With two, it refuses to guess and drops the sentence. That can lose a sentence that was true. I chose to fail closed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It restated the buyer's claim in its own words.&lt;/strong&gt; "The buyer says I have not received my order [E4]." The verifier flagged &lt;em&gt;received&lt;/em&gt;, which isn't in E4, and dropped the sentence. A paraphrase that's fair to a human got cut. That is the cost of a word-level check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With the rules removed, it turned into a customer-service bot.&lt;/strong&gt; On a minimal prompt, Gemma wrote "Thank you for reaching out" and "I understand your concern that the package never arrived, despite the tracking." The verifier flagged &lt;em&gt;never&lt;/em&gt; and the uncited line after it. I also added a check that rejects apologies and admissions unless the evidence itself contains them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The numbers.&lt;/strong&gt; "First draft clean" means the verifier found nothing wrong in the model's first attempt. All rows are Gemma 3 4B on one ASUS laptop (about 46% of the model on the GPU), on 30 generated cases (26 scored; 4 were fold verdicts).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;Runs scored&lt;/th&gt;
&lt;th&gt;First draft clean&lt;/th&gt;
&lt;th&gt;Content dropped&lt;/th&gt;
&lt;th&gt;Attempts&lt;/th&gt;
&lt;th&gt;Seconds/case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Full prompt, 1 run per case&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;92% (24 of 26)&lt;/td&gt;
&lt;td&gt;4%&lt;/td&gt;
&lt;td&gt;1.04&lt;/td&gt;
&lt;td&gt;25.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full prompt, 3 runs per case&lt;/td&gt;
&lt;td&gt;77&lt;/td&gt;
&lt;td&gt;94% (72 of 77)&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;1.03&lt;/td&gt;
&lt;td&gt;25.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimal prompt, no fine-tune&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;0% (0 of 26)&lt;/td&gt;
&lt;td&gt;50%&lt;/td&gt;
&lt;td&gt;2.0&lt;/td&gt;
&lt;td&gt;42.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The three-run row isn't three independent confirmations: three of its five non-clean runs are the same case. Put differently, 23 of 26 cases were clean in every run. One run failed with an Ollama server error and is not counted.&lt;/p&gt;

&lt;p&gt;Cutting the prompt to save time made the model worse and slower, because every case needed a second attempt. In fairness, the minimal prompt is designed for a fine-tuned model, and I ran it on the untuned one. It shows what happens when the rules are left out.&lt;/p&gt;

&lt;p&gt;Earlier, on 15 runs of 3 hand-built cases, 40% of first drafts were clean when the model wrote the photo sentences, and 60% with the stricter prompt. Letting code write them gave 100% clean on those same cases. That 100% is on cases I tuned against, so it is not a held-out number. On 20 unseen generated cases an earlier build scored 95%, and on 12 scored runs of a harder generator on a CPU-only laptop it scored 67%. Those came from different builds and machines, so I'm not claiming a trend. On the same 6 cases on the ASUS, the full prompt gave 4 of 6 clean and the minimal prompt 1 of 6.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limits&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Etsy policy and checklist are placeholders. No real policy is encoded.&lt;/li&gt;
&lt;li&gt;The verifier checks words, not meaning. A misleading rearrangement of true facts can pass.&lt;/li&gt;
&lt;li&gt;Every case is synthetic, written by my own generator, and the samples are small.&lt;/li&gt;
&lt;li&gt;The win score is a heuristic I made up.&lt;/li&gt;
&lt;li&gt;On a CPU-only laptop it took about 136 seconds per case on my harder cases.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Dispute data is customer data: names, addresses, messages. Because Gemma's weights are open, the whole thing runs on the seller's own machine, offline, and none of it leaves. There's no per-token bill either, only electricity.&lt;/p&gt;

&lt;p&gt;Open weights also let me do the work this project needed. I could read every raw draft, find that the model invents photo details, and build a verifier around its mistakes. I could pin one model file and rerun the same 30 cases to get the numbers above. With a closed hosted model I couldn't fix which version answered or inspect what it did between releases. The price is speed: a 4B model on a laptop is slow, and I've measured exactly how slow.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma 3 4B, running locally through Ollama, writes every letter, and all the measurements above are Gemma runs.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
    </item>
    <item>
      <title>TerraQuest: Put the Phone in Your Pocket, Let an Open-Weight Model Name the Animals and Plan</title>
      <dc:creator>Aniruddha Shirke</dc:creator>
      <pubDate>Thu, 08 Oct 2026 20:46:18 +0000</pubDate>
      <link>https://dev.to/aniruddha_shirke_10/terraquest-put-the-phone-in-your-pocket-let-an-open-weight-model-name-the-animals-and-plan-kc8</link>
      <guid>https://dev.to/aniruddha_shirke_10/terraquest-put-the-phone-in-your-pocket-let-an-open-weight-model-name-the-animals-and-plan-kc8</guid>
      <description>&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;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Most outdoor apps want your eyes on the screen. &lt;strong&gt;TerraQuest wants them on the trail.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TerraQuest is a walking companion that tracks your walk in the background, speaks a small mission to you, and names the plants, birds, insects and other wildlife you photograph. Tap Start, put the phone in your pocket, and walk. When something catches your eye, take one photo. The app identifies it, pins it on the map where you found it, and saves it to a journal you read after the walk, not during it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it keeps the screen short&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Walks track themselves.&lt;/strong&gt; GPS distance, active time and estimated calories run without you touching anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missions are read aloud.&lt;/strong&gt; Prompts like "listen for a bird for 10 seconds" are spoken, and you can answer by voice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rewards follow walking, not scrolling.&lt;/strong&gt; XP and streaks come from walks and finds. A day with no walk doesn't count.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The journal is for later.&lt;/strong&gt; Each walk saves its route, the photos of what you found, and a short report.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nearby places&lt;/strong&gt; are suggested from OpenStreetMap, with walking directions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why walking
&lt;/h3&gt;

&lt;p&gt;Regular brisk walking is one of the simplest habits you can build. It is linked to better heart health, mood, sleep and energy, and it needs no gym or equipment. The hard part is keeping it up. TerraQuest gives a walk a reason: a bird to listen for, a plant to find, a streak to keep. Turning "I should walk" into "I wonder what's around the corner" is the whole idea. (Calories are estimates from GPS and time, not medical data.)&lt;/p&gt;

&lt;p&gt;Many people walk past plants and birds they've never learned the names of, and learning them usually means stopping to search on a screen. TerraQuest is for anyone curious about nature who doesn't want to look down at a phone, from families on a weekend stroll to people building a daily walking habit.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Live app:&lt;/strong&gt; [&lt;a href="https://terra-quest-hazel.vercel.app/" rel="noopener noreferrer"&gt;https://terra-quest-hazel.vercel.app/&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%2Fjm081ckqgjbnhaohvpkw.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%2Fjm081ckqgjbnhaohvpkw.png" alt="TerraQuest home screen showing the Start Walk button and daily streak" width="780" height="1688"&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%2F63kqbuxhzj471gjnw5s6.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%2F63kqbuxhzj471gjnw5s6.png" alt="TerraQuest map with the walking route, find pins and nearby spots" width="780" height="1688"&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%2F09b8ctlikx8dv5zy5apv.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%2F09b8ctlikx8dv5zy5apv.png" alt="TerraQuest journal showing a saved walk with photos and a report" width="603" height="808"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The first scan downloads the on-device model once. After that, scanning works without a connection.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest" rel="noopener noreferrer"&gt;https://github.com/Aniruddhashirke/TerraQuest&lt;/a&gt; (MIT licensed)&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/Aniruddhashirke" rel="noopener noreferrer"&gt;
        Aniruddhashirke
      &lt;/a&gt; / &lt;a href="https://github.com/Aniruddhashirke/TerraQuest" rel="noopener noreferrer"&gt;
        TerraQuest
      &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;🌿 TerraQuest&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;A mobile-first outdoor companion.&lt;/strong&gt; Go for a walk, scan the plants, birds and insects you meet, and watch your journal, map and stats fill up. It's a PWA that installs on your phone and works offline.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a9084302dcd151eca34083f7b8bb1ec8c11a946e714c64a8c41789bbb4fb2cb8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f52656163742d31382d3631646166623f6c6f676f3d7265616374266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/a9084302dcd151eca34083f7b8bb1ec8c11a946e714c64a8c41789bbb4fb2cb8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f52656163742d31382d3631646166623f6c6f676f3d7265616374266c6f676f436f6c6f723d7768697465" alt="React"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b9873a28dbd9710d7617388ea3499246b92271b2d3804f0744c11680f5ce6f6d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f547970655363726970742d352d3331373863363f6c6f676f3d74797065736372697074266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/b9873a28dbd9710d7617388ea3499246b92271b2d3804f0744c11680f5ce6f6d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f547970655363726970742d352d3331373863363f6c6f676f3d74797065736372697074266c6f676f436f6c6f723d7768697465" alt="TypeScript"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/4e5aab196491f9343e162cc7bd73c3463a8f4352fc7329ec2d8de22c60f69b6b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f566974652d352d3634366366663f6c6f676f3d76697465266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/4e5aab196491f9343e162cc7bd73c3463a8f4352fc7329ec2d8de22c60f69b6b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f566974652d352d3634366366663f6c6f676f3d76697465266c6f676f436f6c6f723d7768697465" alt="Vite"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ed09a003dcc5a9cfb3f1806a79459440f965d69bd3788edc16ae05d2bd95b517/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5057412d6f66666c696e652d2d66697273742d356130666338"&gt;&lt;img src="https://camo.githubusercontent.com/ed09a003dcc5a9cfb3f1806a79459440f965d69bd3788edc16ae05d2bd95b517/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5057412d6f66666c696e652d2d66697273742d356130666338" alt="PWA"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/21679b490d3a181cacc571dc52597fb1d714341f2dd8bc3d56bc43897a1ca3dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f417574682d476f6f676c6525323025324225323050686f6e652d6666636132383f6c6f676f3d6669726562617365266c6f676f436f6c6f723d626c61636b"&gt;&lt;img src="https://camo.githubusercontent.com/21679b490d3a181cacc571dc52597fb1d714341f2dd8bc3d56bc43897a1ca3dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f417574682d476f6f676c6525323025324225323050686f6e652d6666636132383f6c6f676f3d6669726562617365266c6f676f436f6c6f723d626c61636b" alt="Firebase Auth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Table of contents&lt;/h2&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#features" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#app-flow" rel="noopener noreferrer"&gt;App flow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#screens" rel="noopener noreferrer"&gt;Screens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#how-it-works" rel="noopener noreferrer"&gt;How it works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#tech-stack" rel="noopener noreferrer"&gt;Tech stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#project-structure" rel="noopener noreferrer"&gt;Project structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#getting-started" rel="noopener noreferrer"&gt;Getting started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#environment-variables" rel="noopener noreferrer"&gt;Environment variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#sign-in-setup-google--phone" rel="noopener noreferrer"&gt;Sign-in setup (Google + phone)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#scripts" rel="noopener noreferrer"&gt;Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#testing" rel="noopener noreferrer"&gt;Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#deploying" rel="noopener noreferrer"&gt;Deploying&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#troubleshooting" rel="noopener noreferrer"&gt;Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#roadmap" rel="noopener noreferrer"&gt;Roadmap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aniruddhashirke/TerraQuest#credits-and-data-sources" rel="noopener noreferrer"&gt;Credits and data sources&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sign in with Google or your phone number&lt;/strong&gt; (SMS code), or continue as a guest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Home dashboard&lt;/strong&gt;: nearest nature spot, Today / Week / All time stats, weekly goal ring with streak, daily mission and recent finds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Walk tracking&lt;/strong&gt;: GPS route, distance (Haversine with outlier filtering), active time and estimated calories. Steps show "unavailable" rather than being faked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan and identify&lt;/strong&gt;: take a photo of a plant, bird or insect. A cloud vision model names it…&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/Aniruddhashirke/TerraQuest" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;start walk
   |
   v
GPS route + timer (runs in the background)
   |
   v
photo of a plant, bird, insect or animal
   |
   +-- online? --&amp;gt; cloud vision model --&amp;gt; name + scientific name
   |                    |
   |                    +-- plant? --&amp;gt; Pl@ntNet second opinion
   |
   +-- offline, slow, or error --&amp;gt; CLIP on the device (Transformers.js)
   |
   v
result card --&amp;gt; saved to the journal with photo, GPS and time
   |
   v
map pins + route --&amp;gt; next mission --&amp;gt; stop walk --&amp;gt; report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Identification on the device (open model)
&lt;/h3&gt;

&lt;p&gt;The open-weight model is &lt;strong&gt;CLIP ViT-B/32&lt;/strong&gt; (&lt;code&gt;Xenova/clip-vit-base-patch32&lt;/code&gt;), running in the browser through &lt;strong&gt;Transformers.js&lt;/strong&gt;. It is a zero-shot classifier, so there is no training and no server. The photo is scored against about 70 nature labels, which I tuned to birds, plants and insects common on Indian walks, such as bulbul, myna, banyan and tulsi.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. A cloud upgrade, and an honest fallback
&lt;/h3&gt;

&lt;p&gt;When the phone is online, the photo also goes to my own serverless function, which asks a cloud vision model for a common and scientific name. The API key never reaches the browser. If the call fails, times out after 25 seconds, or there is no signal, the app drops back to CLIP without an error screen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onLine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;identifyOnline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloud&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* fall back */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;device&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result card always tells you which path produced the answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Missions: rules first, AI second (Gemma)
&lt;/h3&gt;

&lt;p&gt;A deterministic engine picks the next mission from your context: how far you've walked, how many plants and birds you've found, and a cooldown so you don't get the same mission twice. &lt;strong&gt;Gemma&lt;/strong&gt; (open weights, running in the browser over WebGPU, [model variant]) only rewords the text and writes the optional &lt;strong&gt;walk note&lt;/strong&gt; after your walk. If it is offline, slow, or returns something odd, a built-in template is used. The prompt says never to invent a species.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Everything is stored on the device
&lt;/h3&gt;

&lt;p&gt;Walks, finds, missions and your profile live in &lt;strong&gt;IndexedDB through Dexie&lt;/strong&gt;, so the app shell and your saved data keep working with no signal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other pieces:&lt;/strong&gt; React 18 and TypeScript, Vite with a PWA service worker, Leaflet with OpenStreetMap and Overpass for nearby places and routes, Wikipedia for species summaries, the browser speech APIs for voice, and Firebase Auth for optional sign-in (guests work fine). Vitest covers the mission rules, geo math, stats, journal reports and identification parsing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Open Matters Here
&lt;/h2&gt;

&lt;p&gt;A trail is the worst place for an app that needs a network.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It works where the walk happens.&lt;/strong&gt; With CLIP on the device, a scan doesn't depend on cell coverage. A cloud-only identifier stops at the edge of signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Photos stay on the phone&lt;/strong&gt; on that path. That matters for family walks and private land.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing per scan.&lt;/strong&gt; There is no per-image bill for a free walking app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's hackable.&lt;/strong&gt; The model is one constant and the label list is a plain array. Anyone can fork it, swap the model, or add their own region's species.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where the closed model was better:&lt;/strong&gt; it gives sharper common and scientific names, while zero-shot CLIP is coarser and will say "kingfisher" where a cloud model might name the exact species.&lt;br&gt;
&lt;strong&gt;Where open won:&lt;/strong&gt; it's the only version that works with no signal, keeps photos private, and costs nothing. That's why the cloud model is an optional upgrade, not the foundation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Went Wrong, and What I Changed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;npm install&lt;/code&gt; failed on a second machine.&lt;/strong&gt; Transformers.js pulls in &lt;code&gt;sharp&lt;/code&gt; and &lt;code&gt;onnxruntime-node&lt;/code&gt;, whose native downloads fail on Windows and restricted networks. The browser app never uses them, so I set &lt;code&gt;ignore-scripts=true&lt;/code&gt; in &lt;code&gt;.npmrc&lt;/code&gt; and stopped copying &lt;code&gt;node_modules&lt;/code&gt; between machines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A zero-shot classifier always has to pick something.&lt;/strong&gt; Show it a phone screen or a face and it will confidently name a bird. I added decoy labels like "phone screen", "person" and "building" so non-nature photos land there instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It can still be wrong.&lt;/strong&gt; In testing, a colourful coleus leaf came back as "fern" at 69%. Confidence is shown on every result, and the cloud model and Pl@ntNet exist to correct cases like this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model output can't be trusted.&lt;/strong&gt; The cloud answer is parsed as JSON and validated: categories are whitelisted, confidence is clamped between 0 and 1, text lengths are capped, and anything malformed triggers the CLIP fallback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plant identification can hurt people.&lt;/strong&gt; The prompt tells the model never to say whether anything is edible, poisonous or safe to touch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adding Gemma broke the production build.&lt;/strong&gt; Its WebGPU runtime is about 6 MB and the PWA precache limit is 2 MB. Instead of raising the limit, I made it a lazy chunk, cached only the first time someone taps &lt;strong&gt;Write a walk note&lt;/strong&gt;. The main app stayed small.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign-in worked locally but failed once deployed&lt;/strong&gt; with &lt;code&gt;auth/unauthorized-domain&lt;/code&gt;. Firebase only allows sign-in from authorized domains, so I added the live domain in the console. Guest mode keeps the app usable regardless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browsers have no step sensor.&lt;/strong&gt; Rather than faking a step count, the app shows steps as unavailable and uses GPS distance for missions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public OpenStreetMap servers are fair-use.&lt;/strong&gt; Nearby results are cached for 30 minutes so the app doesn't hammer them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bird sound identification with &lt;strong&gt;BirdNET&lt;/strong&gt;, an open model, so you can identify a bird without looking at the screen at all.&lt;/li&gt;
&lt;li&gt;Separate local data for each signed-in account.&lt;/li&gt;
&lt;li&gt;Restoring an in-progress walk after a reload.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Map data © OpenStreetMap contributors. Species summaries from Wikipedia. Plant second opinions from &lt;a href="mailto:Pl@ntNet"&gt;Pl@ntNet&lt;/a&gt;. Built with React, Vite, Dexie, Leaflet, Firebase, Transformers.js and Gemma.&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Week 1 Theme: Touch Grass (primary category)&lt;/li&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;li&gt;General Hacktoberfest Open-Source AI Challenge&lt;/li&gt;
&lt;/ul&gt;

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