<?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: Yuvraj Singh</title>
    <description>The latest articles on DEV Community by Yuvraj Singh (@y_uvraj).</description>
    <link>https://dev.to/y_uvraj</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%2F4172496%2Fb8b2fe5c-c4df-4a1d-a04a-148198bde9dd.png</url>
      <title>DEV Community: Yuvraj Singh</title>
      <link>https://dev.to/y_uvraj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/y_uvraj"/>
    <language>en</language>
    <item>
      <title>Meet Moss: a 3D desktop sloth you can talk to. She does your chores and brags about it.</title>
      <dc:creator>Yuvraj Singh</dc:creator>
      <pubDate>Sun, 25 Oct 2026 16:28:36 +0000</pubDate>
      <link>https://dev.to/y_uvraj/meet-moss-a-3d-desktop-sloth-you-can-talk-to-she-does-your-chores-and-brags-about-it-40e1</link>
      <guid>https://dev.to/y_uvraj/meet-moss-a-3d-desktop-sloth-you-can-talk-to-she-does-your-chores-and-brags-about-it-40e1</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;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%2Fjkwpuz19ta06gkze24pd.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%2Fjkwpuz19ta06gkze24pd.png" alt="First" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The theme was "rewards laziness". So I did the laziest thing I could think of: I spent days building an AI so I would never have to right-click the recycle bin again.&lt;/p&gt;

&lt;p&gt;Building her took far longer than the chores will ever take. I know. I'm committed to the bit.&lt;/p&gt;

&lt;p&gt;Meet &lt;strong&gt;Moss&lt;/strong&gt; 🦥, a small 3D sloth who lives on my taskbar. I talk, she listens, she thinks, she answers out loud, and when I ask nicely she does the boring stuff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What she does for me right now:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Empties the recycle bin.&lt;/strong&gt; She tells me how many items and how much space first, then waits for a "yes". It's permanent and I have trust issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Takes notes and reads them back.&lt;/strong&gt; Ask "what did I note today?" and she summarises the day out loud.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skips songs&lt;/strong&gt; (next, previous) and &lt;strong&gt;changes the volume&lt;/strong&gt; ("a little quieter", "a lot louder", mute).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keeps a lazy score.&lt;/strong&gt; Every chore she does gets counted, with an estimate of the time saved, and then she brags:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"That's 11 chores and about 9 minutes today. I'm proud of us."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rewarding laziness is the whole challenge, so I put it in the product itself. Moss is lazy, proud of it, and keeps receipts.&lt;/p&gt;

&lt;p&gt;She is also just a good desktop pet. She sits on my windows, follows my cursor with her eyes, dances when my music plays, and falls asleep if I go quiet for too long. Extremely on theme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who gets to be lazier?&lt;/strong&gt; Me, mostly. And anyone who has ever lost a fight with the Windows volume slider.&lt;/p&gt;

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

&lt;p&gt;&lt;iframe src="https://player.mux.com/80082U00Cw7e01yRQWlAtEqjDVe6MOhdvrJBAH00xddgp8Y" width="710" height="399"&gt;
&lt;/iframe&gt;

&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/YuvrajSHAD/Desktop-Companion" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Everything runs &lt;strong&gt;on my own PC&lt;/strong&gt;. No cloud, no API keys, no "your sloth is currently unavailable".&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Open model / tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ears&lt;/td&gt;
&lt;td&gt;Whisper large-v3-turbo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brain&lt;/td&gt;
&lt;td&gt;Gemma 4 (e4b) through Ollama&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Voice&lt;/td&gt;
&lt;td&gt;Kokoro-82M, a Japanese girl voice speaking English, because it's adorable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Body&lt;/td&gt;
&lt;td&gt;Electron + three.js + three-vrm: a see-through, always-on-top window that is click-through everywhere except the sloth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Credit where it's due:&lt;/strong&gt; the 3D character is &lt;strong&gt;"Zainab-Chan" by mimenn_&lt;/strong&gt;, from &lt;a href="https://hub.vroid.com/en/characters/542563936448829639/models/1717281170322434139" rel="noopener noreferrer"&gt;VRoid Hub&lt;/a&gt;. I didn't make her and I'm not allowed to redistribute her, so she's not in my repo (the README explains how to download her). The voice, the brain, the chores and the code that moves her are mine.&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%2Fp2t55h8fli19e6dyhg5m.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%2Fp2t55h8fli19e6dyhg5m.png" alt="How Moss works: mic to Whisper to a strict matcher, with Gemma as the fallback, then a chore or a reply through Kokoro and the 3D body" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The part I'm proud of: two brains, one bouncer
&lt;/h3&gt;

&lt;p&gt;Letting an LLM decide everything would be slow, and a little scary. What if it empties the bin because I muttered "I should clean up"?&lt;/p&gt;

&lt;p&gt;So Moss works like a club:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The bouncer (a strict matcher)&lt;/strong&gt; handles clear commands instantly. "Next song." "Empty the recycle bin." No thinking, no delay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The friend who gets you (Gemma)&lt;/strong&gt; only steps in when something &lt;em&gt;sounds&lt;/em&gt; like a command but isn't clear, like "flip to the following song". Gemma has to answer with a JSON verdict (Ollama structured output), so she can't ramble her way into deleting something.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything else is just chat.&lt;/strong&gt; "Skip the intro" and "what's the next song on that album?" never trigger a chore.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  I measured it instead of guessing
&lt;/h3&gt;

&lt;p&gt;I wrote a script that throws &lt;strong&gt;60 different ways of saying each of 9 commands&lt;/strong&gt; at Moss (540 phrasings), plus &lt;strong&gt;60 normal sentences that must not trigger anything&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7kxww1f9b1scvyxtzl9g.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%2F7kxww1f9b1scvyxtzl9g.png" alt="Bar chart of accuracy per command, strict matcher only versus strict matcher plus Gemma. Overall 69 percent versus 92 percent" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Strict matcher&lt;/th&gt;
&lt;th&gt;Strict + Gemma&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;recycle bin&lt;/td&gt;
&lt;td&gt;57%&lt;/td&gt;
&lt;td&gt;98%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;take a note&lt;/td&gt;
&lt;td&gt;67%&lt;/td&gt;
&lt;td&gt;92%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;next song&lt;/td&gt;
&lt;td&gt;57%&lt;/td&gt;
&lt;td&gt;98%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;previous song&lt;/td&gt;
&lt;td&gt;58%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;volume up&lt;/td&gt;
&lt;td&gt;70%&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;volume down&lt;/td&gt;
&lt;td&gt;68%&lt;/td&gt;
&lt;td&gt;83%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mute&lt;/td&gt;
&lt;td&gt;72%&lt;/td&gt;
&lt;td&gt;87%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;read my notes&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;td&gt;93%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lazy score&lt;/td&gt;
&lt;td&gt;92%&lt;/td&gt;
&lt;td&gt;92%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;All commands (540)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;69%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;92%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Normal sentences wrongly treated as a command (of 60)&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Gemma took Moss from "gets about two thirds of how I talk" to "gets about 9 in 10".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where she still struggles:&lt;/strong&gt; volume and mute are the weakest (83 to 87%), and Gemma let one normal sentence through as a command. 1 in 60. I'm reporting it anyway, because a sloth should be honest.&lt;/p&gt;

&lt;p&gt;She's careful in other ways too. She only presses the media keys while Spotify is running, so she can't skip my YouTube by accident. The link between her body and her brain is localhost-only and needs a random token.&lt;/p&gt;

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

&lt;p&gt;A sloth who can empty my recycle bin and read my notes is basically a tiny surveillance device with great manners. I did &lt;strong&gt;not&lt;/strong&gt; want her sending my voice, my notes and my file activity to somebody else's server.&lt;/p&gt;

&lt;p&gt;Open models made that easy to avoid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;My voice and notes never leave my PC.&lt;/strong&gt; Whisper, Gemma and Kokoro all run locally, so privacy is the default, not a setting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I could build the "understanding" step around the model.&lt;/strong&gt; Structured JSON output from a local Gemma is what lets a strict matcher and an LLM work as a team. I could also measure it, rerun it and fix it, which is hard to do with someone else's black box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I picked her voice by ear.&lt;/strong&gt; I auditioned a few Japanese voices and kept my favourite in minutes. No vendor, no sign-up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No API bill, no rate limit, no outage.&lt;/strong&gt; Moss never has a "service unavailable" day. Just regular sloth days.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Here is how Moss's time savings are counted. I wrote down how long each chore takes me by hand, and she adds them 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%2F476zwfqtrv62vqcwi4e5.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%2F476zwfqtrv62vqcwi4e5.png" alt="Bar chart of estimated hand-time per chore in seconds: recycle bin 45, read notes 40, take a note 30, previous song 12, next song 10, volume 8, mute 5" width="799" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;These are estimates, not stopwatch readings.&lt;/strong&gt; Treat her score as "roughly this lazy". She doesn't claim more.&lt;/p&gt;

&lt;p&gt;The real payoff isn't the seconds. It's that I can say "volume down", "next song" or "take a note" without leaving whatever I'm doing, and it just happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next: the big lazy idea
&lt;/h2&gt;

&lt;p&gt;Right now every chore in Moss is hand-coded. One chunk of code for the bin, another for notes, another for Spotify. That is... not very lazy. 😅&lt;/p&gt;

&lt;p&gt;The plan is to stop writing features one at a time. I want a proper framework so Moss can work with software on her own, and a new chore is something she &lt;em&gt;figures out&lt;/em&gt;, not something I write at 2am. Think "Moss, rename these screenshots" or "Moss, clean up my Downloads folder", with her working out how to do it safely, asking before anything permanent, and telling me what she did.&lt;/p&gt;

&lt;p&gt;The "ask first before anything permanent" habit from the recycle bin stays exactly as it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  A word from Moss
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Thank you for reading all the way down here. That was a lot of effort. I'm going to take a nap now."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Gemma.&lt;/strong&gt; Gemma 4 is the brain of Moss. It is the fallback that understands loose, human phrasing and answers in strict JSON, it writes the spoken summary of my notes, and it does the talking when I just want to chat. In my test it lifted command accuracy from 69% to 92% across 540 phrasings.&lt;/p&gt;

&lt;p&gt;Thanks for participating! 🦥&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn 🦥
&lt;/h2&gt;

&lt;p&gt;I'd love your take on these:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What's the one boring PC chore you'd hand to a voice assistant first?&lt;/strong&gt; I'll build the best answers into Moss next.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Should she interrupt me when something looks wrong, or wait until I ask?&lt;/strong&gt; I'm planning a version that notices suspicious processes, and I can't decide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What's the least useful thing you've spent days automating?&lt;/strong&gt; Mine is a recycle bin, music, taking notes, summarizing my notes next thing in morning. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The part I'm least sure about: Gemma lets 1 in 60 normal sentences through as a command. If you've handled that better, tell me how.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>gemma</category>
    </item>
    <item>
      <title>I Built an AI That Scores Sensitive Data Entirely Offline - No Cloud, No Data Leaks</title>
      <dc:creator>Yuvraj Singh</dc:creator>
      <pubDate>Fri, 16 Oct 2026 14:48:02 +0000</pubDate>
      <link>https://dev.to/y_uvraj/i-built-an-ai-that-scores-sensitive-data-entirely-offline-no-cloud-no-data-leaks-l1h</link>
      <guid>https://dev.to/y_uvraj/i-built-an-ai-that-scores-sensitive-data-entirely-offline-no-cloud-no-data-leaks-l1h</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;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%2Fxnpqn4opntk3nvungmx6.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%2Fxnpqn4opntk3nvungmx6.png" alt="Airgap cover" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Airgap&lt;/strong&gt; is a desktop-style web dashboard that turns a spreadsheet into risk scores, with no cloud, no training run and no data scientist. You drop in a CSV or Excel file, pick one of three jobs, and TabPFN (Prior Labs' tabular foundation model) scores every row on your own GPU. A local LLM then writes the one-page summary. Nothing leaves the machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;Small teams sit on small, sensitive tables: a few hundred to a few thousand rows. The tools that would help them either need a data scientist to tune a model, or they send the data to a cloud service they are not allowed to use.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Who&lt;/th&gt;
&lt;th&gt;Their table&lt;/th&gt;
&lt;th&gt;Why the cloud is off the table&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Clinical labs and researchers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Patient records with lab markers&lt;/td&gt;
&lt;td&gt;Patient privacy rules (HIPAA / GDPR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Small plants and machine shops&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Batch records with temperature, vibration, purity&lt;/td&gt;
&lt;td&gt;Operational data they will not put on someone else's server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Credit unions and micro-lenders&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Past loan outcomes&lt;/td&gt;
&lt;td&gt;Credit and financial privacy rules (FCRA / GLBA)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Who would pay
&lt;/h3&gt;

&lt;p&gt;The buyer is whoever holds the table and cannot upload it. My hypothesis for the side hustle: one person installs Airgap on a clinic, plant or lender's own machine and charges per site or per seat. This is untested. I have not sold it yet, and the licensing note in "Why Open Innovation Matters" applies before anyone charges for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The three modes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;You get&lt;/th&gt;
&lt;th&gt;Built-in demo data&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🩺 &lt;strong&gt;Clinical risk&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Risk score and tier per patient, the three columns that moved each score, a one-page clinician summary&lt;/td&gt;
&lt;td&gt;Synthetic patients, or &lt;strong&gt;real&lt;/strong&gt; hospital readmission data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🏭 &lt;strong&gt;Industrial yield / failure&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Expected yield with an &lt;strong&gt;80% range&lt;/strong&gt; (flags batches that fall outside it), or a machine-failure score&lt;/td&gt;
&lt;td&gt;Real semiconductor sensor data, synthetic machine-failure data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💳 &lt;strong&gt;Credit default&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Default risk, approve / review / decline bands, a cutoff slider, reason codes, an approvals-vs-bad-loans chart&lt;/td&gt;
&lt;td&gt;Real credit-card default data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Decision support, not a decision-maker.&lt;/strong&gt; Scores should never replace a clinician, an engineer or a credit committee. The dashboard says so, and so do the generated summaries.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;&lt;br&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%2F1nk05gsq1uq9k7gefowm.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%2F1nk05gsq1uq9k7gefowm.png" alt="Dashboard" width="799" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the demo shows:&lt;/strong&gt; loading real hospital data, pressing &lt;strong&gt;Score it&lt;/strong&gt;, and getting scored rows, tiers, drivers and a written summary, all on a laptop RTX 4090 with the network unplugged.&lt;/p&gt;
&lt;h3&gt;
  
  
  Real result: hospital readmission
&lt;/h3&gt;

&lt;p&gt;Real data: &lt;em&gt;Diabetes 130-US Hospitals&lt;/em&gt; (UCI, CC BY 4.0), 8,000 rows and 47 columns. 7,800 rows have a known outcome. 200 have a blank outcome and are scored as "new patients".&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cross-validated AUC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.67&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.5 is a coin flip, 1.0 is perfect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Event rate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12%&lt;/td&gt;
&lt;td&gt;Share of known patients readmitted within 30 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Top-decile lift&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.4x&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The top 10% of scores hold 2.4 times the overall event rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Run time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;269 s&lt;/td&gt;
&lt;td&gt;Full pipeline on a laptop RTX 4090 (16 GB): 5-fold CV, final fit, explanations, summary&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I am showing this number on purpose. Readmission is a noisy outcome, and an AUC around 0.67 is realistic for it. A dashboard that reported 0.99 on this data would be hiding a leak. Known rows are always scored &lt;strong&gt;out-of-fold&lt;/strong&gt;, so a patient's own outcome never helps score that patient.&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%2Fjrzmhz6g43jvqwju3ct6.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%2Fjrzmhz6g43jvqwju3ct6.png" alt="What moves the outcome" width="799" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The strongest driver, number of prior inpatient visits, is also the best-known predictor for this dataset, which is a useful sanity check. The model drivers show &lt;em&gt;influence on the score&lt;/em&gt;, not causation. For example, "A1C result missing" mostly reflects who gets tested.&lt;/p&gt;


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

&lt;p&gt;&lt;a href="https://github.com/YuvrajSHAD/Airgap" rel="noopener noreferrer"&gt;https://github.com/YuvrajSHAD/Airgap&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;airgap/
├── server.py            FastAPI app, job queue (one analysis at a time keeps the GPU predictable)
├── app/
│   ├── engine.py        TabPFN wrapper: picks CUDA when torch sees it, exposes GPU name to the UI
│   ├── analysis.py      CSV -&amp;gt; features -&amp;gt; cross-validation -&amp;gt; final fit -&amp;gt; explanations
│   ├── narrative.py     local LLM summary with a number guardrail + template fallback
│   └── samples.py       synthetic demo data
├── static/index.html    the whole UI: one file, loads nothing from the internet
├── prepare_datasets.py  downloads and cleans the four real datasets
├── check_gpu.py         times a real TabPFN run on the GPU and caches the weights
├── install.bat          CUDA build of PyTorch, dependencies, GPU check
└── run.bat              starts the server offline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run it (Windows, NVIDIA GPU):&lt;/strong&gt; run &lt;code&gt;install.bat&lt;/code&gt; once while online, then &lt;code&gt;run.bat&lt;/code&gt;. After the first weight download, it starts in offline mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&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%2Fwqpa5e46fq1y3ye67ghk.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%2Fwqpa5e46fq1y3ye67ghk.png" alt="Airgap pipeline" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; TabPFN (3.5 weights) · PyTorch with CUDA 12.8 · FastAPI · pandas and scikit-learn · Ollama running &lt;code&gt;qwen3:8b&lt;/code&gt; · a single static HTML page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. TabPFN does all the scoring.&lt;/strong&gt; There is no model to train and no hyperparameters. Your known rows are the &lt;em&gt;context&lt;/em&gt;, and TabPFN predicts from them in one forward pass. Classification gives calibrated probabilities. Regression gives a prediction plus an &lt;strong&gt;80% interval&lt;/strong&gt;, which powers the yield mode's "outside the expected range" flag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Honest accuracy by default.&lt;/strong&gt; Rows with a known outcome are scored by &lt;strong&gt;5-fold cross-validation&lt;/strong&gt; (3-fold for very large files). Rows with a blank outcome are scored from everything known. The dashboard's accuracy numbers come from the first group, so they are not flattered by memorization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Explanations by occlusion.&lt;/strong&gt; For the 10 columns most related to the outcome, I swap in a typical value and watch the score move. The columns that move it most are listed per record, with an up or down arrow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. A local LLM that is not allowed to invent numbers.&lt;/strong&gt; &lt;code&gt;qwen3:8b&lt;/code&gt; writes the summary through Ollama from a small JSON of facts. Every number in its text is checked against the results. If the model cites a figure that was not in the facts, the summary is rejected and a built-in template is used instead. The page tells you which one you got and why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Cleaning real data without cheating.&lt;/strong&gt; &lt;code&gt;prepare_datasets.py&lt;/code&gt; drops columns that give away the answer (for example, the five failure-type columns in the machine dataset), removes patients who died or went to hospice (they cannot be readmitted), keeps the best-filled sensors &lt;em&gt;without looking at the outcome&lt;/em&gt;, and blanks the outcome on the last rows so the "new rows" path is exercised.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three things that broke (and what they taught me)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"It uses my CPU, not my 4090."&lt;/strong&gt; &lt;code&gt;pip install torch&lt;/code&gt; on Windows gives the CPU-only build, and pip happily treated an existing CPU build as "already satisfied". The fix was a forced reinstall of the CUDA 12.8 build. No CUDA Toolkit is needed, only the NVIDIA driver. The top bar now shows the GPU name, or a red "CPU only".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TabPFN's browser licence login crashed inside a &lt;code&gt;.bat&lt;/code&gt; file&lt;/strong&gt; on Windows. The scripts now read an API key from a local file and turn the browser flow off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The LLM summary silently fell back to the template.&lt;/strong&gt; My model-name check matched on a prefix, so a different model of the same family counted as "installed". Now the check is exact, and the page states the reason whenever the LLM is not used.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Honest limits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;TabPFN is &lt;strong&gt;slower per run&lt;/strong&gt; than a gradient-boosting model. Its value is near-best accuracy with zero tuning, not speed.&lt;/li&gt;
&lt;li&gt;My timing on the 8,000-row file is 269 s. Smaller tables, which are the intended use, are much faster. In my GPU check, a 1,500-train / 500-test fit and predict took 1.34 s once warm.&lt;/li&gt;
&lt;li&gt;Results come from cross-validation on public datasets, so they show how the model does on held-out rows from the same source. I have not tested on data from a different hospital, plant or lender, so a new site’s numbers could differ.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Because the whole product is a promise: your data never leaves your computer. A closed API cannot make that promise.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open weights make the air gap real.&lt;/strong&gt; TabPFN's weights sit on the local disk. After a one-time download, Airgap runs with the network off, and telemetry is disabled. A hosted prediction API would mean uploading patient records, plant telemetry or loan histories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero cost per prediction.&lt;/strong&gt; Score ten rows or ten thousand and nothing is metered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swappable parts.&lt;/strong&gt; The summary model is one setting (&lt;code&gt;LLM_MODEL&lt;/code&gt;). Any Ollama model works, and the guardrail keeps whichever one honest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspectable.&lt;/strong&gt; A clinic's IT team can read the code, see that nothing phones home, and decide for themselves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;A caveat I want to be upfront about:&lt;/strong&gt; TabPFN's weights are open-weight under Prior Labs' licence. The free licence is &lt;strong&gt;non-commercial&lt;/strong&gt;, so selling Airgap would need a commercial licence from Prior Labs. This is a hackathon prototype, and checking that licence is the first step of the side hustle.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of TabPFN.&lt;/strong&gt; TabPFN is the engine for all three modes and the only thing producing scores: classification probabilities, regression with 80% intervals, categorical and missing-value handling without preprocessing, and a CUDA path on a local RTX 4090. It runs on real public datasets with honest out-of-fold evaluation. The local LLM only narrates results, and its text is checked against them. Note: TabPFN is the core of a dashboard, not an MCP-driven prediction agent.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>tabpfn</category>
      <category>ai</category>
    </item>
    <item>
      <title>Elsewhere: Meet Your Friends In your Free Time</title>
      <dc:creator>Yuvraj Singh</dc:creator>
      <pubDate>Fri, 09 Oct 2026 04:59:00 +0000</pubDate>
      <link>https://dev.to/y_uvraj/elsewhere-dont-remind-me-give-me-a-reason-22fl</link>
      <guid>https://dev.to/y_uvraj/elsewhere-dont-remind-me-give-me-a-reason-22fl</guid>
      <description>&lt;h1&gt;
  
  
  Elsewhere — Don't Remind Me. Give Me a Reason.
&lt;/h1&gt;

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

&lt;p&gt;&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%2Fxcqwo3k8b5aax6vnpeti.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%2Fxcqwo3k8b5aax6vnpeti.png" alt="Elsewhere app screenshot" width="799" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Try It and Explore the Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://sidequest-touchgrass.onrender.com/" rel="noopener noreferrer"&gt;https://sidequest-touchgrass.onrender.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub repository:&lt;/strong&gt; &lt;a href="https://github.com/YuvrajSHAD/touchgrass-ai" rel="noopener noreferrer"&gt;https://github.com/YuvrajSHAD/touchgrass-ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hugging Face Space:&lt;/strong&gt; &lt;a href="https://huggingface.co/spaces/zoroxR/elsewhere-qwen" rel="noopener noreferrer"&gt;https://huggingface.co/spaces/zoroxR/elsewhere-qwen&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The web app is deployed on Render. Although the Hugging Face Space and local inference integrations have been tested separately, the active AI provider in the public deployment has not yet been verified.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Less time deciding what to do. More time actually doing it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🌱 The Idea
&lt;/h2&gt;

&lt;p&gt;We don't need another app telling us to go outside. Most of us already know we should.&lt;/p&gt;

&lt;p&gt;The harder part is deciding what to do with the free time we have.&lt;/p&gt;

&lt;p&gt;You're sitting at your laptop, scrolling on your phone, and a simple question comes up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Okay, what should I actually do?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Elsewhere&lt;/strong&gt; around a different idea:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't just remind people to go outside. Give them a reason to.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you're into photography, have 30 minutes free, and a friend happens to be nearby. Instead of throwing fifty activities at you, Elsewhere uses that context to suggest one small, actionable outdoor quest.&lt;/p&gt;

&lt;p&gt;The AI isn't the destination. &lt;strong&gt;The outside world is.&lt;/strong&gt;&lt;/p&gt;

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



&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    A["Your interests"] --&amp;gt; D["Elsewhere"]
    B["Time available"] --&amp;gt; D
    C["Nearby friend context"] --&amp;gt; D
    D --&amp;gt; E["Generate one outdoor quest"]
    E --&amp;gt; F["Close the app"]
    F --&amp;gt; G["Go do something"]
    style D fill:#d9f99d,stroke:#3f6212,color:#1a2e05
    style G fill:#bbf7d0,stroke:#166534,color:#14532d&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Three inputs. One suggestion. No endless feed.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your friend is nearby, and you both have 20 minutes. Meet up and explore somewhere you wouldn't normally go.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The intended experience is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Elsewhere.&lt;/li&gt;
&lt;li&gt;Get a reason.&lt;/li&gt;
&lt;li&gt;Close the app.&lt;/li&gt;
&lt;li&gt;Go outside.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🛠️ The Technical Architecture
&lt;/h2&gt;

&lt;p&gt;Elsewhere is a Progressive Web App (PWA) backed by Node.js and Express. Its suggestion pipeline supports hosted Hugging Face inference, optional local inference through llama.cpp, and a deterministic fallback.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    U["Browser / PWA"] --&amp;gt; API["Node.js + Express"]
    API --&amp;gt; CTX["Build suggestion prompt&amp;lt;br/&amp;gt;Interests · Duration · Friend context"]
    CTX --&amp;gt; HF{"Hugging Face&amp;lt;br/&amp;gt;Space configured?"}
    HF --&amp;gt;|Yes| HFI["Qwen3 1.7B&amp;lt;br/&amp;gt;ZeroGPU inference"]
    HFI --&amp;gt;|Usable response| OUT["Clean suggestion"]
    HFI --&amp;gt;|Failure / no usable text| LOCAL{"Local LLM configured?"}
    HF --&amp;gt;|No| LOCAL
    LOCAL --&amp;gt;|Yes| LLAMA["llama.cpp&amp;lt;br/&amp;gt;OpenAI-compatible API"]
    LLAMA --&amp;gt;|Usable response| OUT
    LLAMA --&amp;gt;|Failure / no usable text| FALLBACK["Deterministic fallback"]
    LOCAL --&amp;gt;|No| FALLBACK
    OUT --&amp;gt; RESP["Return suggestion"]
    FALLBACK --&amp;gt; RESP
    RESP --&amp;gt; U&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The diagram describes the backend's intended provider-selection and fallback logic. It does &lt;strong&gt;not&lt;/strong&gt; establish that every path works in the deployed Render environment.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Purpose&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;HTML, CSS, JavaScript, PWA&lt;/td&gt;
&lt;td&gt;User experience&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Node.js, Express&lt;/td&gt;
&lt;td&gt;API and suggestion orchestration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosted AI&lt;/td&gt;
&lt;td&gt;Hugging Face Space&lt;/td&gt;
&lt;td&gt;Qwen3 inference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local AI&lt;/td&gt;
&lt;td&gt;llama.cpp&lt;/td&gt;
&lt;td&gt;Local OpenAI-compatible inference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;Qwen3 1.7B&lt;/td&gt;
&lt;td&gt;Generates short outdoor suggestions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Render&lt;/td&gt;
&lt;td&gt;Hosts the web app and backend&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  🧠 Following a Suggestion Through the System
&lt;/h2&gt;

&lt;p&gt;Here's the request lifecycle in a little more detail.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    participant U as User
    participant W as Web App
    participant S as Express Server
    participant H as Hugging Face
    participant L as Local llama.cpp

    U-&amp;gt;&amp;gt;W: Select interests and available time
    W-&amp;gt;&amp;gt;S: POST /api/suggestion
    S-&amp;gt;&amp;gt;S: Build contextual prompt
    alt Hugging Face configured
        S-&amp;gt;&amp;gt;H: Request Qwen3 suggestion
        H--&amp;gt;&amp;gt;S: Inference result
    else Hosted provider unavailable or unusable
        S-&amp;gt;&amp;gt;L: Try local inference if configured
        L--&amp;gt;&amp;gt;S: Model response or failure
    end
    S-&amp;gt;&amp;gt;S: Clean result or use fallback
    S--&amp;gt;&amp;gt;W: Return suggestion
    W--&amp;gt;&amp;gt;U: Display one outdoor quest&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The server owns provider selection and response handling. The browser doesn't need to know which model generated the suggestion.&lt;/p&gt;

&lt;p&gt;That separation also makes it possible to test inference independently of the public deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔬 What I Actually Tested
&lt;/h2&gt;

&lt;p&gt;I wanted to distinguish a working integration from an architecture that merely looks good on paper.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Local llama.cpp health endpoint&lt;/td&gt;
&lt;td&gt;Passed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local app → llama.cpp suggestion request&lt;/td&gt;
&lt;td&gt;Passed during testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local app → Hugging Face Space inference&lt;/td&gt;
&lt;td&gt;Successful response observed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hugging Face Space direct demo&lt;/td&gt;
&lt;td&gt;Tested successfully&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full browser and geolocation flow&lt;/td&gt;
&lt;td&gt;Not fully verified&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI inference through the public Render deployment&lt;/td&gt;
&lt;td&gt;Not verified&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One successful hosted-inference test returned:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find a quiet spot to do calisthenics and enjoy the breeze.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The local integration also returned a model-generated response through the app's suggestion endpoint.&lt;/p&gt;

&lt;p&gt;These checks confirmed that both inference paths could produce responses during their respective tests. They don't prove continuous availability or successful inference on every request.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔌 Why Open-Weight AI?
&lt;/h2&gt;

&lt;p&gt;I wanted to explore what a small, focused application could do with open-weight AI without making every interaction dependent on a closed, hosted API.&lt;/p&gt;

&lt;p&gt;Using Qwen3 with a Hugging Face Space gives the project a hosted inference path. Supporting llama.cpp also gives me a way to run inference locally through an OpenAI-compatible API.&lt;/p&gt;

&lt;p&gt;The trade-offs are different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hosted inference:&lt;/strong&gt; Easier to access without running a model on your own machine, but dependent on service availability and usage limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local inference:&lt;/strong&gt; More control over where the model runs, but requires a compatible server and sufficient local resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic fallback:&lt;/strong&gt; Keeps the suggestion flow useful when a model isn't configured or returns no usable response.
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    A["Suggestion request"] --&amp;gt; B{"Inference available?"}
    B --&amp;gt;|Hosted| C["Hugging Face + Qwen3"]
    B --&amp;gt;|Local| D["llama.cpp + Qwen3"]
    B --&amp;gt;|Neither| E["Fallback template"]
    C --&amp;gt; F["One suggestion"]
    D --&amp;gt; F
    E --&amp;gt; F&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;For this project, AI is a means to an end. It should make the suggestion more relevant, not turn a five-minute decision into a twenty-minute conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔒 Privacy and Product Decisions
&lt;/h2&gt;

&lt;p&gt;Elsewhere is deliberately designed to resist becoming another attention-consuming product.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No endless feeds.&lt;/li&gt;
&lt;li&gt;No streaks or gamification loops.&lt;/li&gt;
&lt;li&gt;No notification loops.&lt;/li&gt;
&lt;li&gt;No endless AI conversations.&lt;/li&gt;
&lt;li&gt;Nearby-friend context is intended to help people make plans, not encourage constant checking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current backend uses in-memory state for group and presence data, rounds location information, and expires presence after a limited period. The exact privacy properties still depend on the implemented flows and deployment configuration.&lt;/p&gt;

&lt;p&gt;The guiding principle is simple: &lt;strong&gt;help people spend less time on the screen, not more.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 My Agent Session
&lt;/h2&gt;

&lt;p&gt;I used DevRelay to document the repository architecture, trace the suggestion-generation flow, and test the local LLM integration.&lt;/p&gt;

&lt;p&gt;The session separates source-code findings from results verified through live local checks, while identifying behavior that remains untested.&lt;/p&gt;


&lt;div class="ltag-agent-session"&gt;
  &lt;div class="agent-session-header"&gt;
    
    &lt;span class="agent-session-tool-icon-badge" title="GitHub Copilot"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;Tracing Elsewhere's Local LLM Suggestion Flow&lt;/span&gt;
  &lt;/div&gt;

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

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Inspect my existing Elsewhere project read-only. Trace suggestion generation, the local LLM integration and fallback, check local model status, and if practical perform a harmless suggestion-endpoint test. Do not read .env, reveal secrets, modify project files, or publish. Separate source-verified findings, live test results, and unverified behavior. Show the detailed findings and proposed transcript before saving.&lt;/p&gt;

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

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-inspectprojectreadonly"&gt;inspect_project_read_only&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Read README.md, web/package.json, web/server.js, web/.env.example, llm/README...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Read README.md, web/package.json, web/server.js, web/.env.example, llm/README.md; inspect web/public/app.js only to trace client suggestion and nearby-context flow; inspect llm/models filenames only. Do not read .env.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Source inspection: README names the project Elsewhere - TouchGrass and describes a local-first PWA for friend proximity, saved interests, and outdoor side quests. web/package.json specifies Node &amp;gt;=20, ES modules, Express 5, start=node server.js and dev=node --watch server.js. server.js serves public assets and JSON APIs, defaults to port 3000, stores groups/members in an in-memory Map, rounds coordinates to three decimals, and expires presence after 10 minutes. In public/app.js, makeSuggestion obtains nearby results, then sends interests, duration, and nearbyFriend to POST /api/suggestion. The normal nearby lookup obtains geolocation and posts presence, which updates in-memory state; this path was not used in the smoke test. POST /api/suggestion normalizes interests, limits them to 12, defaults duration to 20 and clamps it to 5-180, then calls llmSuggestion. With no LLM_BASE_URL it returns a deterministic template. With a base URL it posts to {LLM_BASE_URL}/chat/completions, passing model, available time, interests, and nearby-friend context in a prompt asking for one short actionable outdoor quest. Non-2xx/network/timeout errors are logged as LLM ERROR and use the template; empty model text also uses the template. LLM_TIMEOUT_MS defaults to 15000 ms. .env.example shows port 3000 and example LLM_BASE_URL http://localhost:8080/v1; the real .env was not opened. llm/README.md documents llama.cpp POST /v1/chat/completions at localhost:8080/v1 and says no cloud inference; it does not specify a concrete server launch command, only to use the command appropriate to installed llama.cpp and model. llm/models contains only .gitkeep. README web run steps are cd web; npm install; cp .env.example .env; npm run dev. No project files were changed.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-safelocallivechecks"&gt;safe_local_live_checks&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;GET the local llama.cpp health and model-list endpoints. Temporarily start th...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;GET the local llama.cpp health and model-list endpoints. Temporarily start the existing Node web server, inspect its health response, POST synthetic sample data only to the stateless /api/suggestion route, capture the returned suggestion and whether an LLM error was logged, then stop the temporary server. Do not call location or presence endpoints.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Live checks: llama.cpp GET /health returned HTTP 200 and {status: ok}; GET /v1/models returned HTTP 200 with two model entries (identifiers omitted). The web server was initially not listening. It was started temporarily; GET /api/health reported llmConfigured=true. A stateless POST /api/suggestion with interests=[birdwatching], duration=20, nearbyFriend=true returned: Your friend could join you in chasing the early morning song of a flickerfoot butterfly. This differs from the deterministic template for the sample and no LLM ERROR was logged, verifying the local model was reached through the app. No real location, circle, or presence endpoint was used. The temporary app process was stopped.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Verified from source: the documented local web run steps are cd web, npm install, cp .env.example .env, npm run dev. The local LLM README expects llama.cpp at localhost:8080/v1 and does not supply one specific launch command. Verified live: llama.cpp health was OK, two model entries were listed, and the app returned a model-generated suggestion with llmConfigured=true and no LLM error. Not tested: full documented install/run flow, real browser/geolocation/circle flow, and the public Render deployment. Render AI configuration was not inspected, so no claim is made about its provider. The actual .env, credentials, and private paths were not read or included. No project files were changed.&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;

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


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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Render — Best Use of Render:&lt;/strong&gt; Hosting the Elsewhere web app and backend on Render.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ElevenLabs — Best Use of ElevenLabs:&lt;/strong&gt; Generating AI narration for the Elsewhere product demo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entire — Best Use of Entire:&lt;/strong&gt; Sharing the DevRelay session documenting Elsewhere's architecture and local LLM integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub — Best Use of GitHub Copilot:&lt;/strong&gt; Using Copilot to inspect the codebase, trace suggestion generation, and test the local LLM integration.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The next step is to verify the full deployed inference path and browser experience, then continue refining how the app turns a person's interests and available time into a genuinely useful suggestion.&lt;/p&gt;

&lt;p&gt;The goal isn't to build the biggest AI application.&lt;/p&gt;

&lt;p&gt;It's to build one that gives someone a good reason to close it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Less scrolling. More elsewhere.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you try it, I'd love to hear: &lt;em&gt;Would one personalized outdoor suggestion actually get you off your screen?&lt;/em&gt;&lt;/p&gt;

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