<?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: Anmol </title>
    <description>The latest articles on DEV Community by Anmol  (@amyy22).</description>
    <link>https://dev.to/amyy22</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%2F4168900%2Fd75cfc40-d8d4-4ec3-b870-2833b66d7f54.jpg</url>
      <title>DEV Community: Anmol </title>
      <link>https://dev.to/amyy22</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amyy22"/>
    <language>en</language>
    <item>
      <title>Somewhere Out There, Forgotten Accounts Still Have My Name, I Went Looking: So I built Ghostbook, a Gemma-Powered Map of Your Forgotten Accounts.</title>
      <dc:creator>Anmol </dc:creator>
      <pubDate>Sun, 01 Nov 2026 06:32:30 +0000</pubDate>
      <link>https://dev.to/amyy22/somewhere-out-there-forgotten-accounts-still-have-my-name-i-went-looking-so-i-built-ghostbook-a-2g3p</link>
      <guid>https://dev.to/amyy22/somewhere-out-there-forgotten-accounts-still-have-my-name-i-went-looking-so-i-built-ghostbook-a-2g3p</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The story
&lt;/h2&gt;

&lt;p&gt;It starts with a small moment.&lt;/p&gt;

&lt;p&gt;You open an app you have not touched in a year. Maybe it is a food delivery app, an old shopping site, a course platform you signed up for in a burst of motivation. The screen asks for an email. You type the one you always use.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;No account found with this email.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You pause. You try your other Gmail. The one you made in college. The one you made for "serious things." The one you made because you forgot the password to the first one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;No account found with this email.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now you are not sure there is an account at all. Maybe you signed up with Facebook. Maybe you used a username instead of an email, and you have no idea what you typed that day. You sit there with the cursor blinking, and you feel something odd for such a small problem: a tiny sting of embarrassment. You are locked out of something you made yourself.&lt;/p&gt;

&lt;p&gt;So you do what everyone does. You click &lt;strong&gt;Forgot password? Reset here.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And the reset email goes to an inbox you stopped checking two years ago, or it never comes, or it says "if an account exists, we have sent a link," which tells you nothing. You close the app. Whatever you came here to do, you do not do it.&lt;/p&gt;

&lt;p&gt;I have lived this loop more times than I can count, and I started to notice something. The problem was never the password. Password managers are good at that. The problem was three questions I could no longer answer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Which email did I use?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What was my username?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How do I get back in?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every account you create quietly produces those three facts, and then your brain throws them away. Multiply that by a few hundred apps and websites, and you are carrying a hidden pile of lost context.&lt;/p&gt;

&lt;p&gt;Then the theme of this challenge arrived: &lt;strong&gt;Ghost in the Machine.&lt;/strong&gt; And it clicked. Every forgotten account is a ghost. It is something you made, abandoned, and lost track of. It still holds your name, your email, and maybe your address or your orders, sitting in a database you have not thought about in years. It is haunting your inbox, and you cannot even find it.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;So I built Ghostbook&lt;/strong&gt; is a map of your online accounts, not a vault of passwords. It remembers which email you signed up with, which username you picked, and how to reset access, so the next time you forget, "Forgot password" works on the first click. Gemma, an open-weight model, turns messy notes into structured entries, answers questions about your accounts in plain language, and writes a haunting report about the forgotten accounts lurking in your life.&lt;/p&gt;

&lt;p&gt;Built for the Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine.&lt;/p&gt;

&lt;p&gt;The problem&lt;br&gt;
You signed up for hundreds of apps. For most of them you can no longer answer three questions:&lt;/p&gt;

&lt;p&gt;Which email did I use?&lt;br&gt;
What was my username?&lt;br&gt;
How do I get back in?&lt;br&gt;
So you click "Forgot password", guess an email, get a "no account found" message, and repeat. Every forgotten account is also a ghost: an old login that still holds your data and still sits in someone's database.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Account map. Store site, email, username, login method, reset route, last used date, and notes.&lt;/li&gt;
&lt;li&gt;Paste to account. Paste a signup email or a rough note and Gemma extracts a structured entry for you to review and save.&lt;/li&gt;
&lt;li&gt;Ask your graveyard. Ask "which email did I use for my bank?" and get an answer grounded in your own entries.&lt;/li&gt;
&lt;li&gt;Haunting report. Plain-code checks find stale accounts, one email tied to too many accounts, and entries with no recovery route. Gemma then writes a short, spooky summary.&lt;/li&gt;
&lt;li&gt;Hybrid AI. Run Gemma locally with Ollama, through a cloud API (Groq or Google AI Studio), or local-first with a cloud fallback.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  How It Fits "Ghost in the Machine"
&lt;/h2&gt;

&lt;p&gt;The theme asks for something spooky, or something that honors the past. Ghostbook does both, and the ghost in the title is meant literally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The ghosts are real.&lt;/strong&gt; Every account you made and forgot is a ghost in someone else's machine. It still holds your name, your email, maybe your address and order history, in a database you have not thought about in years. It is not dead, it is just unattended. That is the spooky part: your past self is still out there, keeping a little of you alive without your knowing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The machine is the haunted house.&lt;/strong&gt; Hundreds of apps and websites, each holding a piece of you, each with its own login rules. You cannot walk through them all and check. Ghostbook gives you a map of the house, so you can see where the ghosts are.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Gemma is how the ghosts are found.&lt;/strong&gt; The model reads the messy traces you leave behind (a signup email, a half-remembered note) and turns them into entries. It answers "which email did I use for my bank?" from your own records. Then the haunting report scores your book from &lt;em&gt;Quiet&lt;/em&gt; to &lt;em&gt;Poltergeist&lt;/em&gt; and writes a short, slightly spooky summary of what to deal with first. [Keep the score band names only if they are in your final UI.]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. It honors the past.&lt;/strong&gt; In the spirit of Día de los Muertos, the point is remembering what you left behind instead of letting it fade unseen. The older an account's last-used date, the more its card fades in the ledger, until it becomes a dashed-border ghost. You watch your digital past dim, and then you choose what to keep, secure, or finally let go. [Keep this only if the fading cards are built.]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. It looks ahead to the afterlife.&lt;/strong&gt; Your accounts outlive your attention, and sometimes they outlive you. A "digital ofrenda" mode, a list of accounts a trusted person would need to find, is on the roadmap. That one is not built yet. I am saying so plainly because honoring the past should not start with overclaiming.&lt;/p&gt;
&lt;h2&gt;
  
  
  Gemma powers three features:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Paste to account.&lt;/strong&gt; Paste a signup email or a messy note like "zomato, second gmail, username anmol_k", and Gemma extracts a structured entry. You review it, and nothing is saved until you say so.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask your graveyard.&lt;/strong&gt; Ask "which email did I use for my bank?" and get an answer grounded only in your own entries. If the answer is not there, it says so instead of guessing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Haunting report.&lt;/strong&gt; Plain code finds stale accounts, one email tied to too many accounts, duplicate sites, and entries with no recovery route. Gemma then writes a short, slightly spooky summary of what to clean up first.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The interface leans into the theme quietly. The older an account's last-used date, the more its card fades, until it becomes a dashed-border ghost. You can literally watch your digital past dim. [Keep this paragraph only if the fading cards are built in your final version.]&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;will uplaod soon&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/AnmolCanCodes" rel="noopener noreferrer"&gt;
        AnmolCanCodes
      &lt;/a&gt; / &lt;a href="https://github.com/AnmolCanCodes/Ghostbook" rel="noopener noreferrer"&gt;
        Ghostbook
      &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;Ghostbook&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Find the ghosts haunting your inbox.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ghostbook is a map of your online accounts, not a vault of passwords. It remembers which email you signed up with, which username you picked, and how to reset access, so the next time you forget, "Forgot password" works on the first click. Gemma, an open-weight model, turns messy notes into structured entries, answers questions about your accounts in plain language, and writes a haunting report about the forgotten accounts lurking in your life.&lt;/p&gt;
&lt;p&gt;Built for the Hacktoberfest Open-Source AI Challenge, Week 4: &lt;strong&gt;Ghost in the Machine&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The problem&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;You signed up for hundreds of apps. For most of them you can no longer answer three questions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Which email did I use?&lt;/li&gt;
&lt;li&gt;What was my username?&lt;/li&gt;
&lt;li&gt;How do I get back in?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So you click "Forgot password", guess an email, get a "no account found" message, and repeat. Every forgotten account is…&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/AnmolCanCodes/Ghostbook" 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;&lt;strong&gt;Stack:&lt;/strong&gt; React and Vite on the frontend, FastAPI and SQLAlchemy on the backend, SQLite for storage, and Gemma as the model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  +----------------------------+
                  |   React + Vite frontend    |
                  |  list / add / ask / report |
                  +-------------+--------------+
                                | /api  (Bearer session token, held in memory only)
                  +-------------v--------------+
                  |        FastAPI backend     |
                  |                            |
                  |  routers: auth, accounts,  |
                  |           ai, haunting     |
                  |                            |
                  |  security.py  scrypt + Fernet
                  |  redaction.py strip secrets before any cloud call
                  |  llm.py       provider-agnostic client
                  +------+---------------+-----+
                         |               |
              +----------v---+     +-----v------------------------+
              |   SQLite     |     |  LLM provider (by LLM_MODE)  |
              | encrypted    |     |  local : Ollama              |
              | fields only  |     |  cloud : Groq / Google AI    |
              +--------------+     |  hybrid: local, then cloud   |
                                   +------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  One client, any Gemma
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LLM_MODE=local | cloud | hybrid | off
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This design came from a real constraint. &lt;strong&gt;My laptop cannot run Gemma locally.&lt;/strong&gt; If I had hard-wired one hosted API, that would have been the end of any privacy story. Because the client is provider-agnostic, I built against hosted Gemma while the exact same code runs against a local model on better hardware.&lt;/p&gt;

&lt;h3&gt;
  
  
  Being honest about what leaves your machine
&lt;/h3&gt;

&lt;p&gt;That constraint made me think hard about one question: in cloud mode, what actually gets sent? I did not want to hand-wave it, so each feature sends the minimum it needs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Sent to the cloud provider&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Paste to account&lt;/td&gt;
&lt;td&gt;The pasted text, after passwords, OTPs, card numbers and ID-style numbers are masked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ask your graveyard&lt;/td&gt;
&lt;td&gt;Your question plus a few candidate entries picked by a local keyword filter (site, email, username, login method). Notes stay local by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haunting report&lt;/td&gt;
&lt;td&gt;Aggregate counts only, like "14 stale accounts". No account details&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In hybrid mode, the messages are rebuilt for each provider attempt. If a request falls back from local to cloud, the redaction and minimization are applied at that moment, instead of reusing a payload that was built for the local model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security design
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A master passphrase is set on first run and &lt;strong&gt;never stored&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;scrypt turns it into a key, and every account field is encrypted with Fernet. The database holds ciphertext only.&lt;/li&gt;
&lt;li&gt;The key lives in server memory for the session and is dropped when the vault locks. Sessions expire after idle time, and repeated wrong passphrases trigger a lockout.&lt;/li&gt;
&lt;li&gt;The frontend keeps its token in memory, not in localStorage. Refreshing the page means unlocking again, by design.&lt;/li&gt;
&lt;li&gt;The UI always shows an AI badge (&lt;code&gt;AI: local&lt;/code&gt;, &lt;code&gt;AI: cloud&lt;/code&gt;, and so on), so you can see where your data goes instead of trusting a settings page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Things that were harder than they looked
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Getting reliable structured output from Gemma.&lt;/strong&gt; I could not rely on JSON mode being supported everywhere, so the prompts put all instructions in a single user message, the parser strips code fences and extracts the JSON object, and it retries once with a repair instruction before giving up cleanly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treating pasted text as hostile.&lt;/strong&gt; A signup email can contain anything, including instructions aimed at the model. The prompt marks pasted text as untrusted data, and the model's output is rendered as plain text only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never failing because the AI failed.&lt;/strong&gt; The haunting report falls back to a deterministic template summary if the model is off or unreachable. The ledger itself works with no AI at all.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Where you have accounts is one of the most personal things about you. It reveals your banks, your health apps, your late-night shopping, and the sites you would rather forget. That is exactly the kind of data I do not want locked inside one company's API.&lt;/p&gt;

&lt;p&gt;Open weights gave me three things a closed API would not:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A privacy choice instead of a privacy policy.&lt;/strong&gt; With a closed model, "where does my data go?" is answered by a vendor's terms. With Gemma, it is a setting. In &lt;code&gt;local&lt;/code&gt; mode with Ollama, nothing leaves your machine and the app works with the internet off. In &lt;code&gt;off&lt;/code&gt; mode, search still works with no AI at all. The AI badge in the UI is the app's answer to the question every user should ask.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No lock-in.&lt;/strong&gt; Ollama, Google AI Studio, and Groq all run through the same client. If a provider changes its pricing, retires a model, or disappears, I change one line of config. A tool whose whole purpose is helping you remember things should not die the day someone else's service does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A path from "my laptop can't" to "yours can."&lt;/strong&gt; I built on hosted Gemma because my hardware could not run it. Someone with a stronger machine runs the identical code fully offline. A closed model offers no equivalent of that second option.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Spirit of It
&lt;/h2&gt;

&lt;p&gt;There is an idea in Día de los Muertos that people stay alive as long as someone remembers them. I think accounts work the other way around. They stay alive because &lt;em&gt;nobody&lt;/em&gt; remembers them. Years later they are still there, quiet and forgotten, holding a little piece of who you were when you signed up.&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%2Fqw1a4bzpzvwtzc0z43z0.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%2Fqw1a4bzpzvwtzc0z43z0.png" alt=" " width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I play games like PUBG, Valorant, and chess, but there's one frustrating thing that always catches me off guard: after taking a break or reinstalling a game, I can never remember which Gmail I used, what username I had, or whether I signed up with Google or Facebook. I've wasted time trying to recover accounts I already owned. That's where &lt;strong&gt;Ghostbook&lt;/strong&gt; came from, a personal ledger that remembers the accounts I tend to forget, so the next time I return, I don't have to start guessing all over again.&lt;/p&gt;

&lt;p&gt;Ghostbook will not bring anyone back. But it does something small and kind: it helps you remember what you left behind, and decide what to keep and what to finally let go. On my roadmap is a "digital ofrenda" mode, a list of accounts a trusted person would need to know about. Your accounts outlive your attention, and sometimes they outlive you. Someone should be able to find them.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma is the core of the project. It extracts account entries from messy text, answers questions grounded in the user's own entries, and writes the haunting report summary. It runs locally through Ollama or hosted through Google AI Studio, with the same code.&lt;br&gt;
&lt;strong&gt;Best Use of GitHub Copilot:&lt;/strong&gt; I leveraged GitHub Copilot to streamline architectural planning and accelerate code development. However, all core decisions regarding the product roadmap, workflow execution, feature set, and end-to-end project delivery were entirely my own.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
    </item>
    <item>
      <title>I Had 5,000 Screenshots and Couldn’t Find Any, So I Built: SnapRecall:Type What Text You Remember, Find the Screenshot</title>
      <dc:creator>Anmol </dc:creator>
      <pubDate>Mon, 26 Oct 2026 05:32:10 +0000</pubDate>
      <link>https://dev.to/amyy22/i-had-5000-screenshots-and-couldnt-find-any-so-i-built-snaprecall-type-what-you-remember-find-268c</link>
      <guid>https://dev.to/amyy22/i-had-5000-screenshots-and-couldnt-find-any-so-i-built-snaprecall-type-what-you-remember-find-268c</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;SnapRecall is a screenshot search tool. It watches your screenshots folder, lets an AI model read every image in the background, and builds a private search index. Later, you type whatever you remember about the screenshot ("rahul payment 2500", "docker permission error", "wo flight ticket wala") and the matching screenshots show up.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I got the idea
&lt;/h3&gt;

&lt;p&gt;I take a lot of screenshots. A payment confirmation, a WhatsApp chat I might need as proof, an error message I want to Google later, a ticket, a recipe, a random detail from a group chat. I never organize them, because the whole point of a screenshot is that it takes one second.&lt;/p&gt;

&lt;p&gt;The cost shows up later. My screenshots folder has thousands of files, all named like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;screenshot_2026-10-24-14-55-16.png
screenshot_2026-10-24-14-55-41.png
screenshot_2026-10-24-15-02-07.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When I need one specific image, those names tell me nothing. I end up scrolling through hundreds of nearly identical thumbnails, squinting at each one, and sometimes giving up. It is not a big problem, but it happens often, and it is exactly the kind of tedious work that a computer should do instead of me.&lt;/p&gt;

&lt;p&gt;When I read the "slow and steady" theme, this was the first thing I thought of. It is a task that should happen quietly in the background, with no effort from me, while I do something else.&lt;/p&gt;
&lt;h3&gt;
  
  
  Two ideas, one choice
&lt;/h3&gt;

&lt;p&gt;I had two possible solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rename on save.&lt;/strong&gt; The moment a screenshot is taken, an AI reads it, summarizes it, and renames the file with the important words. A WhatsApp chat about rent becomes something like &lt;code&gt;whatsapp_rahul_rent_payment.png&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search by memory.&lt;/strong&gt; Leave the files alone. When I cannot find a screenshot, I type the words I remember from inside it, and the app shows me the matches.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Renaming looked simple, but when I thought it through, it had problems. A filename is one guess about what I will remember later, and the AI's guess is often not the thing I remember. A screenshot of a chat could be filed under the contact's name, the topic, or the amount, and I might search by any of them. Renaming files can also break references in other apps or sync tools, and after a few thousand files, long auto-generated names start to look the same again.&lt;/p&gt;

&lt;p&gt;Search works with whatever I happen to remember, and it does not touch my files. So I chose search as the core, and I treat smart renaming as a possible add-on for later (with a preview and an undo, not silent changes).&lt;/p&gt;
&lt;h3&gt;
  
  
  Who it is for
&lt;/h3&gt;

&lt;p&gt;Anyone with a messy screenshots folder: students who screenshot notes, developers who save error messages, and people who screenshot payments, chats and tickets as proof. I also built it with Hindi and Hinglish in mind, because that is how I actually think and type. A lot of the text in my screenshots is in Hindi or mixed, and I did not want a tool that only works for clean English.&lt;/p&gt;
&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Background indexing: new screenshots are picked up automatically soon after they are saved&lt;/li&gt;
&lt;li&gt;A slow, throttled backfill of your old screenshots, so a big backlog never needs your attention&lt;/li&gt;
&lt;li&gt;A vision model reads each screenshot and produces a short summary, tags, an app type (chat, payment, code, error, ticket...) and the text it can see&lt;/li&gt;
&lt;li&gt;Hybrid search: keyword matching for exact names, amounts and error codes, plus semantic search for vague memories&lt;/li&gt;
&lt;li&gt;English, Hindi and Hinglish queries&lt;/li&gt;
&lt;li&gt;A simple React interface with a thumbnail grid, a larger preview, and live indexing progress with pause and resume&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;[demo]  &lt;iframe src="https://www.youtube.com/embed/3aeP7lybdDs" width="710" height="399"&gt;
  &lt;/iframe&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/AnmolCanCodes" rel="noopener noreferrer"&gt;
        AnmolCanCodes
      &lt;/a&gt; / &lt;a href="https://github.com/AnmolCanCodes/snaprecall" rel="noopener noreferrer"&gt;
        snaprecall
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      SnapRecall:Find any screenshot by typing what you remember about it..Built for the Hacktoberfest DEV Challenge, Week 3 (theme: "Slow and Steady")
    &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;SnapRecall&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Find any screenshot by typing what you remember about it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SnapRecall watches your screenshots folder, lets an AI model read every image in the background, and builds a searchable index. Instead of scrolling through thousands of files named &lt;code&gt;screenshot_2026-10-24-14-55-16.png&lt;/code&gt;, you type "rahul payment 2500" or "docker permission error" and the matching screenshots appear.&lt;/p&gt;

&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/AnmolCanCodes/snaprecall/SnapRecall%20Screenshot%20Search%20Hero.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FAnmolCanCodes%2Fsnaprecall%2FHEAD%2FSnapRecall%2520Screenshot%2520Search%2520Hero.png" alt="SnapRecall — AI-powered screenshot search" width="100%"&gt;&lt;/a&gt;
  &lt;p&gt;&lt;strong&gt;Find any screenshot by typing what you remember about it.&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;AI-powered screenshot indexing · Hybrid search · English, Hindi &amp;amp; Hinglish&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Built for the Hacktoberfest DEV Challenge, Week 3 (theme: "Slow and Steady").&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;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#the-problem" rel="noopener noreferrer"&gt;The problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#what-snaprecall-does" rel="noopener noreferrer"&gt;What SnapRecall does&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#features" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/AnmolCanCodes/snaprecall#how-it-works" rel="noopener noreferrer"&gt;How it works&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#architecture-overview" rel="noopener noreferrer"&gt;Architecture overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#1-discovery-and-folder-watching" rel="noopener noreferrer"&gt;1. Discovery and folder watching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#2-queue-and-resilient-background-worker" rel="noopener noreferrer"&gt;2. Queue and resilient background worker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#3-indexing-pipeline" rel="noopener noreferrer"&gt;3. Indexing pipeline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#4-hybrid-search-engine" rel="noopener noreferrer"&gt;4. Hybrid search engine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://github.com/AnmolCanCodes/snaprecall#hosted-mode-vs-local-mode" rel="noopener noreferrer"&gt;Hosted mode vs local mode&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#feature-comparison" rel="noopener noreferrer"&gt;Feature comparison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#hosted-mode-gemini-api" rel="noopener noreferrer"&gt;Hosted mode (Gemini API)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#local-mode-ollama" rel="noopener noreferrer"&gt;Local mode (Ollama)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#tech-stack" rel="noopener noreferrer"&gt;Tech stack&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#getting-started" rel="noopener noreferrer"&gt;Getting started&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#configuration" rel="noopener noreferrer"&gt;Configuration&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#api-overview" rel="noopener noreferrer"&gt;API overview&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#project-structure" rel="noopener noreferrer"&gt;Project structure&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#privacy-and-security" rel="noopener noreferrer"&gt;Privacy and security&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#why-open-weight-ai" rel="noopener noreferrer"&gt;Why open-weight AI&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/AnmolCanCodes/snaprecall#troubleshooting" rel="noopener noreferrer"&gt;Troubleshooting&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;…&lt;/li&gt;

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


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

&lt;h3&gt;
  
  
  The stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Python 3.11 and FastAPI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React 18, TypeScript and Vite, with plain CSS and no UI framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage:&lt;/strong&gt; SQLite for everything, with FTS5 for keyword search and &lt;code&gt;sqlite-vec&lt;/code&gt; for vector search&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Folder watching:&lt;/strong&gt; &lt;code&gt;watchdog&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Images:&lt;/strong&gt; Pillow for downscaling and thumbnails&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Models:&lt;/strong&gt; a vision model that reads each screenshot and an embedding model for semantic search, either hosted (Gemini API) or local (Ollama)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional OCR:&lt;/strong&gt; Tesseract, in English and Hindi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SQLite was a deliberate choice. For a personal tool, one file with no database server to install is the right amount of infrastructure, and it holds the metadata, the keyword index and the vector index in the same place.&lt;/p&gt;

&lt;h3&gt;
  
  
  The pipeline
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; +---------------------------------------------------------------------------------------+
 |                                  INGESTION LAYER                                      |
 |                                                                                       |
 |  Screenshots Folder (SCREENSHOT_DIR)                                                  |
 |         │                                                                             |
 |         ├─► [Startup Backfill Scanner] ── (scandir walk, skips temp/ignored files) ──┐ |
 |         │                                                                            ▼ |
 |         └─► [Live Watcher (Watchdog)] ── (write stability check, move/delete sync) ─►│ |
 +--------------------------------------------------------------------------------------│+
                                                                                        │
                                                                                        ▼
 +---------------------------------------------------------------------------------------+
 |                             QUEUE &amp;amp; BACKGROUND WORKER                                 |
 |                                                                                       |
 |  SQLite `images` Table (status: pending ──► processing ──► done / failed)             |
 |         │                                                                             |
 |         │  • Claims newest first (ORDER BY mtime DESC, id DESC)                       |
 |         │  • Throttles between images (WORKER_THROTTLE_SECONDS)                       |
 |         │  • Daily budget tracking &amp;amp; auto-resume at midnight                          |
 |         │  • Exponential backoff on 429 rate limits &amp;amp; retry-after parsing             |
 |         ▼                                                                             |
 +---------------------------------------------------------------------------------------+
                                           │
                                           ▼
 +---------------------------------------------------------------------------------------+
 |                                 INDEXING PIPELINE                                     |
 |                                                                                       |
 |  1. Checksum &amp;amp; Deduplication:                                                         |
 |     Computes SHA-256. If file hash already indexed, copies vector &amp;amp; metadata instantly |
 |     (skips LLM &amp;amp; embedding calls completely — zero cost &amp;amp; instant!).                 |
 |                                                                                       |
 |  2. Image Preprocessing:                                                              |
 |     Reads dimensions, downscales longest side to MAX_IMAGE_SIDE (default 1024px),      |
 |     generates base64 payload.                                                         |
 |                                                                                       |
 |  3. Parallel Extraction:                                                              |
 |     ┌────────────────────────────────────┐    ┌────────────────────────────────────┐  |
 |     │ Vision Analysis (Gemini or Ollama) │    │ Optional OCR (Tesseract eng+hin)   │  |
 |     │ Structured JSON output:            │    │ Extracted verbatim text strings    │  |
 |     │ - summary (concise overview)       │    │ (enabled if OCR_ENGINE=tesseract)  │  |
 |     │ - tags (3-8 categorical tags)      │    │                                    │  |
 |     │ - app_type (chat, payment, code...)│    │                                    │  |
 |     │ - visible_text (Hindi / Hinglish / │    │                                    │  |
 |     │   English verbatim text)           │    │                                    │  |
 |     └─────────────────┬──────────────────┘    └─────────────────┬──────────────────┘  |
 |                       └─────────────────┬───────────────────────┘                     |
 |                                         ▼                                             |
 |  4. Document Text Assembly &amp;amp; Embeddings:                                              |
 |     Combines summary + type + tags + visible text + OCR into unified document text.   |
 |     Generates dense embedding vector (EMBEDDING_DIM = 768).                           |
 |                                                                                       |
 |  5. Storage &amp;amp; Triggers:                                                               |
 |     - Updates `images` table with metadata &amp;amp; status='done'.                           |
 |     - SQLite trigger updates `images_fts` (FTS5 BM25 index with unicode61).           |
 |     - Inserts vector into `vec_images` (sqlite-vec KNN virtual table).                |
 |     - Generates lightweight WebP thumbnail in `data/thumbnails/{id}.webp`.            |
 +---------------------------------------------------------------------------------------+
                                           ▲
                                           │
 +---------------------------------------------------------------------------------------+
 |                              HYBRID SEARCH &amp;amp; RETRIEVAL                                |
 |                                                                                       |
 |  User Query (Search Box) ────────────────────────────────────────────────────────┐    |
 |         │                                                                        │    |
 |         ▼                                                                        ▼    |
 |  [Keyword Search Leg]                                                   [Semantic Leg]|
 |  - Sanitizes query (safe tokens &amp;amp; Devanagari)               - Embeds query with task  |
 |  - BM25 matching via SQLite FTS5                            - KNN vector search via   |
 |  - Extracts highlighted snippets                              sqlite-vec              |
 |         │                                                                        │    |
 |         └───────────────────────────────┬────────────────────────────────────────┘    |
 |                                         ▼                                             |
 |                      [Reciprocal Rank Fusion (RRF_K=60)]                              |
 |                      Fuses ranks: score = Σ (1 / (60 + rank))                         |
 |                      Graceful fallback: degrades to keyword-only if provider offline  |
 |                                         │                                             |
 |                                         ▼                                             |
 |                            FastAPI REST API (/api/search)                             |
 |                                         │                                             |
 |                                         ▼                                             |
 |                   React 18 Frontend (Search, Previews, Progress Bar)                  |
 +---------------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Finding screenshots: the watcher and the queue
&lt;/h3&gt;

&lt;p&gt;On startup, a scanner walks the screenshots folder and queues anything new or changed. It skips hidden files, temporary downloads and unsupported formats, and it cleans up records for files that were deleted. After that, a live watcher takes over. When a new screenshot appears, it waits until the file size stops changing, so it never reads an image the operating system is still writing.&lt;/p&gt;

&lt;p&gt;Every image becomes a row in SQLite with a status (&lt;code&gt;pending&lt;/code&gt;, &lt;code&gt;processing&lt;/code&gt;, &lt;code&gt;done&lt;/code&gt; or &lt;code&gt;failed&lt;/code&gt;). That table is the job queue. The worker claims the newest images first, so the screenshot you took five minutes ago becomes searchable before the ones from last year.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the model does with each screenshot
&lt;/h3&gt;

&lt;p&gt;For every image, the worker:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Computes a SHA-256 hash. If an identical image was already indexed, it copies the existing metadata and vector, and no model call happens at all.&lt;/li&gt;
&lt;li&gt;Downscales the image so its longest side is at most 1024 px by default, which cuts bandwidth and cost.&lt;/li&gt;
&lt;li&gt;Asks the vision model for structured output: a one or two sentence &lt;strong&gt;summary&lt;/strong&gt;, 3 to 8 &lt;strong&gt;tags&lt;/strong&gt;, an &lt;strong&gt;app type&lt;/strong&gt; (one of 13, such as chat, payment, code, error, ticket or email), and the &lt;strong&gt;visible text&lt;/strong&gt;, with names, amounts, error codes and Hindi or Hinglish preserved as written.&lt;/li&gt;
&lt;li&gt;Optionally runs Tesseract OCR in parallel. It is off by default, because the vision model already reads the text.&lt;/li&gt;
&lt;li&gt;Merges all of that into one document, turns it into a 768-dimension embedding, and stores everything, plus a small thumbnail.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The original file is never renamed, moved or modified.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the search is hybrid
&lt;/h3&gt;

&lt;p&gt;There are two very different ways people look for a screenshot, and one search method cannot cover both.&lt;/p&gt;

&lt;p&gt;When the memory is exact (a name, an amount like "2500", an error code), keyword search wins, because semantic search tends to blur exact tokens together. When the memory is vague ("the bus ticket one", "the chat where we decided the date"), keyword search fails unless the words match, while semantic search finds it by meaning.&lt;/p&gt;

&lt;p&gt;SnapRecall runs both and merges the two ranked lists with Reciprocal Rank Fusion, where each result scores the sum of 1 / (60 + rank) across the lists it appears in. A result that ranks well in either list rises to the top, and there are no raw scores on different scales to compare. The keyword side sanitizes the query into safe tokens and handles Devanagari correctly. If the embedding service is unavailable, search falls back to keywords only instead of failing, and the response says it is degraded.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slow and steady, on purpose
&lt;/h3&gt;

&lt;p&gt;For this challenge, the theme decided how the indexer works. Reading thousands of images with a model is heavy, and a tool that tries to do it all at once either freezes your computer or burns through API limits and dies halfway. So the worker is patient by design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It processes one image at a time, with a configurable pause in between&lt;/li&gt;
&lt;li&gt;On an API rate limit (HTTP 429) it reads the &lt;code&gt;Retry-After&lt;/code&gt; header and backs off, and that does not count as a failed attempt&lt;/li&gt;
&lt;li&gt;It supports a daily request budget. When the budget or the provider's quota runs out, it pauses itself and resumes automatically at local midnight&lt;/li&gt;
&lt;li&gt;The queue lives in SQLite, so after a restart it continues with the images that are still pending&lt;/li&gt;
&lt;li&gt;Newest screenshots go first&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You keep working, and the index quietly catches up. The backend also has a pytest suite covering the pieces that are easiest to get subtly wrong, like query sanitizing, rank fusion and the worker's behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  One codebase, two ways to run
&lt;/h3&gt;

&lt;p&gt;The model layer sits behind a single setting, &lt;code&gt;LLM_PROVIDER&lt;/code&gt;. The database, search, worker and interface are identical in both modes.&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;Hosted (&lt;code&gt;gemini&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Local (&lt;code&gt;ollama&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Vision model&lt;/td&gt;
&lt;td&gt;Gemini API (repo default: &lt;code&gt;gemini-3-flash-preview&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Gemma, for example &lt;code&gt;gemma3:4b&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embeddings&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemini-embedding-001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;EmbeddingGemma&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Needs internet&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No, after the models are downloaded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where screenshots go&lt;/td&gt;
&lt;td&gt;Sent to Google's API&lt;/td&gt;
&lt;td&gt;Never leave your machine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardware&lt;/td&gt;
&lt;td&gt;Any laptop&lt;/td&gt;
&lt;td&gt;A GPU or a fast CPU with 8 GB+ RAM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free tier with limits, then pay per request&lt;/td&gt;
&lt;td&gt;Electricity only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I started with a fully local plan. Then I looked at my laptop, which is old and weak, and a vision model would crawl on it. Hosted mode keeps the backend light: the app only watches a folder, writes to SQLite and serves a few endpoints, while the heavy model work happens remotely. That is the mode my demo uses.&lt;/p&gt;

&lt;p&gt;I want to be precise about what is open. In hosted mode, the models are Google's hosted models, and they are not open-weight. The open-weight path is local mode, with Gemma and EmbeddingGemma.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;SnapRecall is designed around the open-weight philosophy:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment freedom:&lt;/strong&gt; The architecture works identically whether connected to hosted APIs or run entirely locally via open-weight models like Gemma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long-term preservation:&lt;/strong&gt; Unlike proprietary cloud services that can deprecate models or shut down APIs, open-weight models remain functional offline indefinitely&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Predictable economics:&lt;/strong&gt; Local processing has zero marginal cost per image, enabling you to index tens of thousands of screenshots without subscription fees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;True privacy:&lt;/strong&gt; Screenshots frequently contain OTPs, bank statements, personal chats, and proprietary code. Open-weight models empower you to keep sensitive personal data completely confidential.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does running your own model mean it works without an internet connection?&lt;/strong&gt;&lt;br&gt;
Yes. In local mode, you pull the models once through Ollama, and the whole pipeline runs without a network connection. A closed API cannot offer that, because the model lives on someone else's server. My demo runs in hosted mode, so I am not presenting offline results here, but the switch is one setting in the same codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it keep personal messages and files on your own machine?&lt;/strong&gt;&lt;br&gt;
This is the strongest reason open weights matter for this project. Screenshots hold OTPs, bank messages, private chats and ID photos, which is some of the most sensitive data on a device. In local mode, nothing leaves the machine: not the images, not the extracted text, not the vectors, and not the search queries. In hosted mode, downscaled screenshots and search queries are sent to the provider over HTTPS, and the README says so plainly. A closed vision API has only that second path. An open model gives the user a choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it let you set it up once and never pay for it again?&lt;/strong&gt;&lt;br&gt;
In local mode, yes. After setup, indexing tens of thousands of screenshots has no per-image cost, and re-indexing is free. That matters for a tool whose whole job is to process a huge number of images, because per-image pricing grows with every backlog and every model change. On the hosted route I used the free tier, and its limits shaped the design directly, which is why the worker is throttled, respects rate limits and has a daily budget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where did the open approach work better than a closed one?&lt;/strong&gt;&lt;br&gt;
I will be honest about both sides. The hosted closed model was the easiest way to get running on a weak laptop. That is a real advantage for convenience. The open route won on three things that matter more for this kind of tool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy.&lt;/strong&gt; A private, fully local mode exists only because open weights exist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Longevity.&lt;/strong&gt; Hosted models get deprecated and APIs get shut down. A model you run yourself keeps working offline indefinitely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability.&lt;/strong&gt; Because the project is not tied to one vendor, moving between providers is a config change and not a rewrite.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a tool that reads people's screenshots, the person who owns them should decide where they go. Open weights are what make that decision possible.&lt;/p&gt;

&lt;p&gt;Before SnapRecall, finding an old screenshot meant scrolling through thumbnails for minutes. Now it means typing a few words.&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%2Fc695x58ck0te8eufphmd.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%2Fc695x58ck0te8eufphmd.png" alt=" " width="800" height="406"&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%2F3f7pbenws4ou8dvzjdcm.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%2F3f7pbenws4ou8dvzjdcm.png" alt=" " width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;It actually saves you a ton of time. Instead of scrolling forever to find a specific screenshot, you just type whatever you remember about it. I dropped the project in the friend's group chat and the hype is real ,everyone wants this to exist, so I'm dropping the whole thing in a few days as soon as possible :)&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; SnapRecall's local mode is built around Gemma. It uses Gemma (for example &lt;code&gt;gemma3:4b&lt;/code&gt;) to read screenshots and EmbeddingGemma for semantic search, all running through Ollama on the user's own machine, and it is selected with a single setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of GitHub Copilot:&lt;/strong&gt; I used GitHub Copilot to plan the architecture and to speed up parts of the code. The decisions about what to build, how the search works and how the indexer behaves were mine, and the project runs end to end.&lt;/p&gt;




&lt;p&gt;Thank you for reading. If you try SnapRecall on your own screenshots folder, I would like to hear how it goes. Issues and ideas are welcome on the repo.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
    </item>
    <item>
      <title>GlowUp Local: Using Open-Source AI to Help Local Businesses Improve Their Online Visibility</title>
      <dc:creator>Anmol </dc:creator>
      <pubDate>Sun, 18 Oct 2026 18:04:50 +0000</pubDate>
      <link>https://dev.to/amyy22/glowup-local-an-open-source-ai-side-hustle-to-help-local-businesses-get-discovered-4c13</link>
      <guid>https://dev.to/amyy22/glowup-local-an-open-source-ai-side-hustle-to-help-local-businesses-get-discovered-4c13</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;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What&lt;/strong&gt;: GlowUp Local is a working prototype for AI-powered local business visibility and competitor intelligence.&lt;br&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Small business owners may struggle to understand their online presence, evaluate nearby competitors, and decide which improvements to prioritize.&lt;br&gt;
&lt;strong&gt;AI&lt;/strong&gt;: Gemma via Hugging Face is the language-model component intended to turn structured business information into actionable recommendations.&lt;br&gt;
&lt;strong&gt;Tech stack&lt;/strong&gt;: Python, FastAPI, React, Vite, Gemma, and a planned Google Places API integration.&lt;br&gt;
&lt;strong&gt;Target users&lt;/strong&gt;: Hotels, guesthouses, restaurants, cafés, local shops, and other small businesses in India.&lt;br&gt;
&lt;strong&gt;Business potential&lt;/strong&gt;: Pay-per-audit reports, subscriptions, and partnerships with local marketing professionals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if&lt;/strong&gt; A small business owner could understand their nearby competition, identify gaps in their online presence, and get practical suggestions to improve their visibility on Google Search and Google Maps without becoming an SEO expert?&lt;/p&gt;

&lt;p&gt;That's the idea behind &lt;strong&gt;GlowUp Local&lt;/strong&gt;, an AI-powered local visibility and competitor intelligence tool I'm building.&lt;/p&gt;

&lt;p&gt;I'm exploring how open-source AI can help local businesses make better-informed decisions about their online presence, while also exploring a potential side hustle that solves a real business problem.&lt;/p&gt;

&lt;p&gt;My initial target market is India, starting with businesses such as hotels, guesthouses, cafés, restaurants, and other local businesses in specific neighborhoods and areas.&lt;/p&gt;

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

&lt;p&gt;GlowUp Local is a working prototype designed to help local businesses understand their online presence, learn from available information about nearby competitors, and discover possible improvements they can make.&lt;/p&gt;

&lt;p&gt;The idea started with a place I know: Varanasi, India.&lt;/p&gt;

&lt;p&gt;When people visit Varanasi, they often have questions. Where should they stay? Which hotel or guesthouse should they consider? Which restaurants are worth exploring? Where can they find local products?&lt;/p&gt;

&lt;p&gt;Discovering a city can be confusing when you're unfamiliar with it.&lt;/p&gt;

&lt;p&gt;But this got me thinking about the other side of the same problem: the businesses that visitors might never discover.&lt;/p&gt;

&lt;p&gt;Varanasi has hotels, guesthouses, cafés, restaurants, saree shops, and many other local businesses. Across India, countless small businesses are trying to reach customers in their own neighborhoods.&lt;/p&gt;

&lt;p&gt;Some businesses may already offer excellent products or services but struggle to communicate their value online. Others may have incomplete business information or lack the time and expertise to understand how they compare with nearby competitors.&lt;/p&gt;

&lt;p&gt;Traditional SEO tools can provide plenty of metrics, but understanding those metrics and turning them into practical actions can be difficult for someone who is busy running a business.&lt;/p&gt;

&lt;p&gt;I wanted to explore a simpler approach.&lt;/p&gt;

&lt;p&gt;What if a business owner could get a clearer picture of their online presence and a prioritized list of possible improvements in one place?&lt;/p&gt;

&lt;h3&gt;
  
  
  How GlowUp Local works
&lt;/h3&gt;

&lt;p&gt;The intended workflow is straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Business information:&lt;/strong&gt; The owner provides details such as their business name, category, address, and the products or services they offer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nearby competitor discovery:&lt;/strong&gt; The application uses Google Places API to retrieve available information about relevant nearby businesses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured comparison:&lt;/strong&gt; The application organizes available business information into data that can be used for an evidence-based comparison.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered recommendations:&lt;/strong&gt; Gemma processes the structured data to help generate prioritized recommendations and practical action steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actionable insights:&lt;/strong&gt; The goal is to help business owners understand what they could improve and decide what to work on first.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, a restaurant might receive suggestions to communicate its menu more clearly, improve available business information, describe its services more effectively, or create a better process for asking satisfied customers for honest reviews.&lt;/p&gt;

&lt;p&gt;The planned recommendation workflow also includes evidence references, confidence levels, and local marketing content drafts.&lt;/p&gt;

&lt;p&gt;The important distinction is that GlowUp Local is not intended to generate generic SEO advice and present it as a personalized competitor analysis. Its recommendations should be grounded in the information available to the application.&lt;/p&gt;

&lt;p&gt;And I'm not promising anyone the number-one position on Google. Search visibility depends on many factors, and no tool can guarantee that outcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is to make local business intelligence easier to understand and turn it into practical next steps.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why could this become a side hustle?
&lt;/h3&gt;

&lt;p&gt;GlowUp Local addresses a problem that local businesses may be willing to pay to solve: understanding their online presence without having to perform all the analysis themselves.&lt;/p&gt;

&lt;p&gt;Potential customers include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hotels and guesthouses that want to improve how they present themselves online.&lt;/li&gt;
&lt;li&gt;Restaurants and cafés that want to communicate their offerings more effectively.&lt;/li&gt;
&lt;li&gt;Local shops and service providers that want to understand their nearby competitive landscape.&lt;/li&gt;
&lt;li&gt;Freelancers and small marketing agencies that want to assist local businesses with data-informed recommendations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm exploring several possible business models: pay-per-audit reports, a freemium offering, recurring subscriptions, or partnerships with local marketing professionals.&lt;/p&gt;

&lt;p&gt;These are potential business models, not validated revenue streams. I haven't acquired my first paying customer yet.&lt;/p&gt;

&lt;p&gt;Before monetizing the product, I need to establish whether its recommendations are useful, whether business owners act on them, and whether they are willing to pay for the value provided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&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%2Fvoc5fy8qdfj8k84iov0g.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%2Fvoc5fy8qdfj8k84iov0g.png" alt=" " 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%2Fcfvjew4ecgivagrd3qkg.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%2Fcfvjew4ecgivagrd3qkg.png" alt=" " width="800" height="281"&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%2Fpwqptjo1oud5lmk6e2qj.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%2Fpwqptjo1oud5lmk6e2qj.png" alt=" " width="800" height="357"&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%2Fxtqyz9q4pzojzfyl0l7y.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%2Fxtqyz9q4pzojzfyl0l7y.png" alt=" " width="800" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/AnmolCanCodes/GlowUp-Local" rel="noopener noreferrer"&gt;https://github.com/AnmolCanCodes/GlowUp-Local&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Open innovation matters to GlowUp Local because I want to explore how accessible AI technology can be used to solve a specific problem for small businesses.&lt;/p&gt;

&lt;p&gt;I'm using &lt;strong&gt;Gemma via Hugging Face&lt;/strong&gt; as the language-model layer for generating business recommendations from structured local business and competitor data.&lt;/p&gt;

&lt;p&gt;The intended workflow is to retrieve available business information, organize it into structured data, and use Gemma to help produce prioritized recommendations, actionable steps, evidence references, confidence levels, and local marketing content drafts.&lt;/p&gt;

&lt;p&gt;Instead of treating an AI model as a black box that simply produces impressive-sounding answers, I want the application to connect its recommendations to available evidence and make the resulting advice useful to a business owner.&lt;/p&gt;

&lt;p&gt;Open-weight models such as Gemma give developers an opportunity to experiment with AI-powered applications without depending exclusively on proprietary model providers. Depending on the model's license, deployment setup, and available computing resources, developers can explore different ways to run models and build workflows around their specific use cases.&lt;/p&gt;

&lt;p&gt;This is particularly relevant to my project because my target customers are small businesses that may not have the budget to hire SEO specialists or purchase expensive marketing tools.&lt;/p&gt;

&lt;p&gt;If I can make business information easier to understand and turn it into useful actions, GlowUp Local could help make certain forms of business analysis more accessible.&lt;/p&gt;

&lt;p&gt;Open-source tools also let developers inspect and improve the surrounding application code, experiment with alternative approaches, and invite contributions from the wider developer community.&lt;/p&gt;

&lt;p&gt;However, open-source AI is not automatically free to operate, accurate, or commercially viable. Inference costs, data quality, model limitations, and the reliability of the recommendations still need to be addressed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For me, open innovation is about using accessible technology to build something useful, testing it against a real-world problem, and improving it through experimentation and community feedback.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Gemma&lt;/strong&gt;: Gemma helps this project by acting as the AI decision-support layer for the business audit.&lt;br&gt;
The web app:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;finds the business and nearby competitors using Google Places
compares the business against them
passes that structured data to Gemma
asks Gemma to generate:
    prioritized recommendations
    action steps
    evidence references from the audit
    confidence levels
    content drafts for local marketing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So Gemma is what turns raw comparison data into useful advice like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“Improve your GMB profile”
“Add service-area keywords”
“Create more location-specific content”
“Improve review and rating signals”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is exactly what the project is about: helping local businesses understand where they stand and what to do next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt; : GitHub Copilot used to help me whenever there are bugs and errors in my codes, it fix them &lt;/p&gt;

&lt;h2&gt;
  
  
  Traction: Where the Project Stands
&lt;/h2&gt;

&lt;p&gt;GlowUp Local is currently at the working-prototype stage.&lt;/p&gt;

&lt;p&gt;I haven't acquired my first real user or test customer yet, so I can't claim validated customer feedback, paying users, or measurable business results.&lt;/p&gt;

&lt;p&gt;I want to learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which recommendations they find genuinely useful.&lt;/li&gt;
&lt;li&gt;Whether the available competitor information helps them identify meaningful improvements.&lt;/li&gt;
&lt;li&gt;Whether the reports are understandable to someone without SEO expertise.&lt;/li&gt;
&lt;li&gt;Which features they would actually pay for.&lt;/li&gt;
&lt;li&gt;What information is missing or unreliable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This feedback will help me decide what to improve before investing more time in advanced features or monetization.&lt;/p&gt;

&lt;p&gt;I'd rather validate the product with real businesses than assume that generating AI recommendations automatically creates value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools &amp;amp; Frameworks
&lt;/h2&gt;

&lt;p&gt;Here's the technology stack behind GlowUp Local:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python:&lt;/strong&gt; Backend development and application logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI:&lt;/strong&gt; Backend API layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React + Vite:&lt;/strong&gt; Frontend application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Places API:&lt;/strong&gt; Planned integration for nearby-business discovery and available place information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma via Hugging Face:&lt;/strong&gt; Open-weight language model used for AI-powered business recommendations.
**GitHub &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools bring together full-stack development, business data, and open-source AI to explore a practical local business use case.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
    </item>
    <item>
      <title>GroundTruth: An Open-Source AI Quest Platform That Rewards Real-World Exploration</title>
      <dc:creator>Anmol </dc:creator>
      <pubDate>Sat, 10 Oct 2026 07:42:50 +0000</pubDate>
      <link>https://dev.to/amyy22/groundtruth-using-open-weight-ai-to-get-people-off-their-screens-and-into-the-world-1dm2</link>
      <guid>https://dev.to/amyy22/groundtruth-using-open-weight-ai-to-get-people-off-their-screens-and-into-the-world-1dm2</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;We have apps to track our steps, apps to track our calories, apps to track our productivity, and even apps that remind us to take breaks from using apps.&lt;/p&gt;

&lt;p&gt;There's something slightly ironic about that.&lt;/p&gt;

&lt;p&gt;We spend so much time looking at screens, even when we're trying to build healthier habits.&lt;/p&gt;

&lt;p&gt;But what if an app didn't just tell you to go outside? What if it gave you an actual reason to do it?&lt;/p&gt;

&lt;p&gt;That's the idea behind &lt;strong&gt;GroundTruth&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;GroundTruth is an open, local-first outdoor quest platform that turns everyday exploration into real-world challenges, photo-based submissions, and measurable progress.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The world is the game. Your actions are the achievements.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of simply counting steps or tracking activity, GroundTruth gives users small outdoor quests that encourage them to observe and explore their surroundings.&lt;/p&gt;

&lt;p&gt;Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sky reflection:&lt;/strong&gt; Photograph the sky reflected in a puddle or window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notice tiny textures:&lt;/strong&gt; Find an interesting texture on a public path, rock, or tree bark.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud imagination:&lt;/strong&gt; Look at the clouds and photograph an unusual shape from a safe location.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need a mountain, a hiking trail, or an entire weekend to participate. Sometimes, all you need is five minutes and a reason to notice something you usually walk past.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Choose your moment:&lt;/strong&gt; Select a time slot such as morning, evening, or night.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discover a quest:&lt;/strong&gt; Browse outdoor challenges with instructions, difficulty levels, estimated time, and proof requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go outside:&lt;/strong&gt; Complete the actual task in the real world.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Submit evidence:&lt;/strong&gt; Upload a photograph of your completed challenge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Earn XP:&lt;/strong&gt; Approved submissions earn experience points and contribute to levels, streaks, and badges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore together:&lt;/strong&gt; Compare weekly XP through regional leaderboards covering country, state, and city.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important part is that the actual challenge happens outside the application. The phone is there to introduce the quest and record the accomplishment, not to become the activity itself.&lt;/p&gt;

&lt;p&gt;GroundTruth is designed for people who want to explore their surroundings, build outdoor habits, and make everyday experiences a little more interesting.&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%2Fulcizu40pu82g3gdxgsi.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%2Fulcizu40pu82g3gdxgsi.png" alt=" " width="800" height="462"&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%2Fmgyxefsy8cg4rtr2sxit.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%2Fmgyxefsy8cg4rtr2sxit.png" alt=" " width="800" height="480"&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%2Fexg1r1kqv1bmvhf5xbbc.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%2Fexg1r1kqv1bmvhf5xbbc.png" alt=" " width="799" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

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

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

&lt;p&gt;The field journal introduces the experience with one simple invitation: "A little less screen. A little more world."&lt;/p&gt;

&lt;p&gt;The Explore section lets users discover quests based on their selected time slot.&lt;/p&gt;

&lt;p&gt;Quest examples include Sky Reflection, Notice Tiny Textures, and Cloud Imagination.&lt;/p&gt;

&lt;p&gt;The leaderboard adds a friendly competitive element by ranking users according to approved weekly quest XP.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/AnmolCanCodes/groundtruth" rel="noopener noreferrer"&gt;https://github.com/AnmolCanCodes/groundtruth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is open source. Feel free to explore the implementation, inspect the architecture, and experiment with it.&lt;/p&gt;

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

&lt;p&gt;I wanted GroundTruth to have a straightforward architecture where the core application logic and AI functionality remain independent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technology stack
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;React + Vite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Python + FastAPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;SQLite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ORM&lt;/td&gt;
&lt;td&gt;SQLAlchemy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;td&gt;JWT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI integration&lt;/td&gt;
&lt;td&gt;Hugging Face InferenceClient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open-weight model&lt;/td&gt;
&lt;td&gt;Google Gemma 7B Instruct&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;p&gt;The application follows this general flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              React + Vite
                   |
                   v
                FastAPI
                   |
          +--------+--------+
          |                 |
          v                 v
    Core Application     AI Service
          |                 |
          v                 v
     SQLAlchemy        Hugging Face
          |             InferenceClient
          v                 |
        SQLite              v
                         Gemma 7B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why I separated AI from the reward system
&lt;/h3&gt;

&lt;p&gt;This was one of my important engineering decisions.&lt;/p&gt;

&lt;p&gt;I didn't want an LLM to have unrestricted authority over user rewards.&lt;/p&gt;

&lt;p&gt;In GroundTruth, Python handles the deterministic application logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quest progression.&lt;/li&gt;
&lt;li&gt;Submission processing.&lt;/li&gt;
&lt;li&gt;XP calculations and rewards.&lt;/li&gt;
&lt;li&gt;Level progression.&lt;/li&gt;
&lt;li&gt;Date-based streak tracking.&lt;/li&gt;
&lt;li&gt;Badge unlocking.&lt;/li&gt;
&lt;li&gt;Weekly regional leaderboard calculations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI works as an assistant layer rather than the authority controlling the entire application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Gemma
&lt;/h3&gt;

&lt;p&gt;GroundTruth integrates Google's open-weight &lt;strong&gt;Gemma 7B Instruct&lt;/strong&gt; model through Hugging Face's InferenceClient.&lt;/p&gt;

&lt;p&gt;I use Gemma for text personalization, with the goal of adapting quest descriptions to individual preferences without changing the underlying challenge requirements.&lt;/p&gt;

&lt;p&gt;The application also supports optional AI-assisted image relevance assessment. This is configurable rather than mandatory, and basic upload validation is handled separately by the backend.&lt;/p&gt;

&lt;p&gt;I wanted to keep the AI service replaceable so that changing the model or inference configuration wouldn't require rewriting the application's core logic.&lt;/p&gt;

&lt;p&gt;The result is an application where AI adds flexibility without becoming a dependency for every operation.&lt;/p&gt;

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

&lt;p&gt;For GroundTruth, open innovation is not just about using an open-weight model because it's available.&lt;/p&gt;

&lt;p&gt;It's about having control over how AI fits into the application.&lt;/p&gt;

&lt;p&gt;I didn't want the entire experience to depend on a single proprietary AI provider or a closed ecosystem.&lt;/p&gt;

&lt;p&gt;Here's why open technology matters for this project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Model flexibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using Gemma gives developers an open-weight model that can be integrated into a self-hosted application.&lt;/p&gt;

&lt;p&gt;The AI layer is separated from the core backend, making it easier to experiment with different compatible models and inference configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Data ownership and self-hosting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GroundTruth uses SQLite and local file storage for its self-hosted setup.&lt;/p&gt;

&lt;p&gt;Developers can run their own instance and maintain control over their application data instead of depending entirely on a centrally operated platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Less vendor dependency&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The personalization layer doesn't need to be permanently tied to one closed AI provider.&lt;/p&gt;

&lt;p&gt;Developers can explore different models and deployment approaches as their requirements evolve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. AI where it actually makes sense&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also believe that not every application decision needs an LLM.&lt;/p&gt;

&lt;p&gt;GroundTruth uses AI for assistance and personalization, while important operations such as reward calculations and progression remain deterministic.&lt;/p&gt;

&lt;p&gt;This makes the application more predictable and easier to reason about.&lt;/p&gt;

&lt;p&gt;For me, open innovation means having the freedom to make those architectural decisions rather than accepting a closed provider's limitations.&lt;/p&gt;

&lt;p&gt;And most importantly, it lets me experiment with AI in a way that encourages people to spend more time in the real world, not more time interacting with an AI interface.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Gemma:
&lt;/h3&gt;

&lt;p&gt;GroundTruth uses Google's open-weight &lt;strong&gt;Gemma 7B Instruct&lt;/strong&gt; through Hugging Face's InferenceClient to personalize outdoor quest descriptions based on user preferences, while preserving the original challenge requirements.&lt;/p&gt;

&lt;p&gt;I chose Gemma because I wanted an AI layer that could be experimented with and configured independently of the core application. AI assists with personalization, while Python handles quest validation, XP, badges, and leaderboard calculations deterministically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The idea is simple: use open-weight AI to make real-world exploration more personal, not to make another screen more addictive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's why I'm submitting GroundTruth for the Best Use of Gemma category.&lt;/p&gt;




&lt;p&gt;A little less screen. A little more world. 🌿&lt;/p&gt;

&lt;p&gt;Thanks for checking out GroundTruth. I'd love to hear what outdoor quest you'd add to it!&lt;/p&gt;

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