<?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: Onkar Raskar</title>
    <description>The latest articles on DEV Community by Onkar Raskar (@onkar_raskar_a9bb8f42d47e).</description>
    <link>https://dev.to/onkar_raskar_a9bb8f42d47e</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%2F4156787%2F40ca6960-7a96-4e7a-a37c-b9907a4bbefa.png</url>
      <title>DEV Community: Onkar Raskar</title>
      <link>https://dev.to/onkar_raskar_a9bb8f42d47e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/onkar_raskar_a9bb8f42d47e"/>
    <language>en</language>
    <item>
      <title>Break Buddy: a private, offline "what should I do right now?" web app</title>
      <dc:creator>Onkar Raskar</dc:creator>
      <pubDate>Sat, 03 Oct 2026 08:40:37 +0000</pubDate>
      <link>https://dev.to/onkar_raskar_a9bb8f42d47e/break-buddy-a-private-offline-what-should-i-do-right-now-web-app-30k4</link>
      <guid>https://dev.to/onkar_raskar_a9bb8f42d47e/break-buddy-a-private-offline-what-should-i-do-right-now-web-app-30k4</guid>
      <description>&lt;p&gt;&lt;em&gt;My entry for the Hacktoberfest 2026 Weekend Challenge: Build for a Friend&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;My friends and I were talking about breaks. Someone takes a 10 minute break and it turns into an hour. Some of us end up scrolling mindlessly, some play games, some just sit there doing nothing.&lt;/p&gt;

&lt;p&gt;The break itself was never the problem. After studying, your brain is tired, and it tries to weigh every option it has. Scrolling wins because it is the only option that needs no decision.&lt;/p&gt;

&lt;p&gt;We didn't want to quit our phones. We wanted something that would just tell us what to do, in that exact moment, so we didn't have to decide.&lt;/p&gt;

&lt;p&gt;I built it for my friend Aryan.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Break Buddy&lt;/strong&gt; is a small web app that runs on his own computer. He taps four things: how much time he has, how he feels, where he is, and who is around. It gives back &lt;strong&gt;one&lt;/strong&gt; suggestion and &lt;strong&gt;one 10-second first step&lt;/strong&gt;. No list of ten ideas.&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%2Fcsufqsur0mq4x4h8ysw7.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%2Fcsufqsur0mq4x4h8ysw7.png" alt="Break Buddy suggesting a quick walk" width="730" height="793"&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%2F5imgknedusdgsr4844zb.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%2F5imgknedusdgsr4844zb.png" alt="Break Buddy UI 2" width="738" height="802"&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%2Fio93caynex7c1yk41p91.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%2Fio93caynex7c1yk41p91.png" alt="Break Buddy UI 3" width="763" height="813"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;A short walkthrough: setting the options, getting a suggestion, and finishing it.&lt;/p&gt;

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

&lt;p&gt;Code: &lt;a href="https://github.com/Onkar-Raskar/Build_for_friend-.git" rel="noopener noreferrer"&gt;View the project on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run it yourself you need &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; and Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ollama pull qwen2.5:3b
pip install -r requirements.txt
streamlit run app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  My first version was wrong in obvious ways
&lt;/h2&gt;

&lt;p&gt;The first version asked a small local model to pick an activity from a list. It told people to play football when they were alone. Aryan and I looked at that and agreed: if a suggestion doesn't fit your real situation, you ignore it and open Instagram.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works now: code decides what's possible, the model only words it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;taps (time, mood, place, who's around)
  -&amp;gt; Python removes every activity that is impossible right now
  -&amp;gt; Python picks one (weighted by mood, goals, variety, history)
  -&amp;gt; a local model writes 2 short sentences + a 10-second first step
  -&amp;gt; the reply is checked; if it fails, a plain fallback is shown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every activity declares where, when, with whom and for how long it makes sense:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;mk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ball&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Get a quick game going with whoever is around: football, badminton, anything&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;move&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;moods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;restless&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bored&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;places&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HOME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;friends&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,),&lt;/span&gt; &lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;intense&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exercise&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A model can forget a rule. Python can't. Football needs friends nearby, outdoors, and daylight hours. A walk to a saved place only appears if the round trip plus a few minutes fits the break. Nothing loud late at night, no calls in a silent library, no videos when the internet is off, no heavy thinking right after studying on a short break.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proof: what the model is allowed to choose from
&lt;/h3&gt;

&lt;p&gt;I ran the real rule engine on fixed situations (sample profile):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Options left&lt;/th&gt;
&lt;th&gt;What shows up / what is blocked&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Library, 11 pm, tired, 10 min, just studied, alone&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Stretch, corridor walk, breathing, eyes rest, music, a short writing task. No calls, no sports, no videos.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Room, 7 pm, bored, 1 hour, friends nearby&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;Card game, chess with someone, a walk with a friend, football, a walk to the park or the cafe.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Room, stressed, 10 min, internet off, just studied&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;Nothing that needs the internet: no videos, no LeetCode, no podcasts, no anime.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outside, 5 min, restless, alone, 10 am&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;Only things that fit 5 minutes. No park walk, no episode, no movie.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outside, 1 hour, restless, &lt;strong&gt;alone&lt;/strong&gt;, 4 pm&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Walk, workout, read, call a friend. &lt;strong&gt;No football, no cards, no chess game, because he's alone.&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Room, 3 pm, tired, 10 min, just studied&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;Stretch, breathing, daylight, music, a short video. No puzzles, no LeetCode, no Japanese words.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The fifth row is the football problem from the first version, now fixed in code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open-source AI mattered here
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy.&lt;/strong&gt; The app knows his mood, his routine and who he hangs out with. With Ollama running the model locally, none of that leaves his computer. There is no account and no server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing to run.&lt;/strong&gt; No API key, no per-request bill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works offline.&lt;/strong&gt; The core app needs no internet. When the internet is off, the app simply stops suggesting anything that needs it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I could swap models in one line.&lt;/strong&gt; The model name is a single constant in the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I could see and control the behavior.&lt;/strong&gt; Because the rules live in my code and the model is replaceable, I could trace every odd suggestion and fix it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Speed on a normal PC (CPU only, no GPU)
&lt;/h3&gt;

&lt;p&gt;I timed the same request from clicking the button to seeing the result.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;1st request (includes loading)&lt;/th&gt;
&lt;th&gt;2nd&lt;/th&gt;
&lt;th&gt;3rd&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;qwen2.5:7b&lt;/td&gt;
&lt;td&gt;47.5 s&lt;/td&gt;
&lt;td&gt;20 s&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;qwen2.5:3b&lt;/td&gt;
&lt;td&gt;24.9 s&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;td&gt;10 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both ran 100% on CPU. Once warm, the two ended up close. The big difference is the first request: 3B halves the cold start. His first complaint was that the app felt slow, so I moved to 3B and made the app load the model in the background when it opens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why there is no live link
&lt;/h2&gt;

&lt;p&gt;I tried to host it, and I'm glad I did, because the attempt taught me something.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit Community Cloud&lt;/strong&gt; runs the interface fine, but there is no Ollama on that server, so the app couldn't reach a model. I changed the app so that when no model is found, it still works and shows the plain, rule-based suggestion with a short note. That version shows the rules, but not the friendly wording.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting the model myself&lt;/strong&gt; meant a paid server with at least 4 GB of RAM, because the 3B model alone is about 2 GB, while the cheapest plan I looked at has 512 MB. It also meant adding a card.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The bigger reason:&lt;/strong&gt; a hosted version would send his mood, routine and friends' names to a server. That is the exact thing this project is meant to avoid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the real app is local on purpose, and I'm sharing a video and the code instead of a live link.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Aryan said
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;The biggest win was the strict, short phrasing. I usually ignore long-winded productivity advice, but getting a simple two-sentence prompt and a 10-second "first step" made it completely frictionless to just drop my phone and knock out 15 squats or clear my desk. It also really nailed the context of living with roommates. Around 7 PM, when my friends were hanging around, I swapped the company setting to "With friends". Instead of telling me to meditate or read alone, it instantly suggested starting a card game or walking over to the cafe for a break. [...] Getting a prompt to do exactly one easy LeetCode problem or watch a single short robotics video kept me from spiraling into a massive YouTube black hole when I only had 15 minutes between study blocks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;His complaints were just as useful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Too many taps.&lt;/strong&gt; He had to set everything again every time. The app now remembers his last settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It was too heavy when he was tired.&lt;/strong&gt; It suggested writing five Japanese words when he had set his mood to "tired". Now, when the mood is tired, anything that needs effort is blocked and only gentle options remain.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What the usage log shows
&lt;/h2&gt;

&lt;p&gt;The app logs what it showed and what he did with it. For the day of testing and real use, the log has 59 events: 39 suggestions shown, 8 skipped, 2 marked "Can't now", 5 started, and 5 finished.&lt;/p&gt;

&lt;p&gt;I won't call that a completion rate. The finished ones were tapped a few seconds after starting, so they show he pressed the button, not that he did the activity. What is more telling is what he rejected: the Japanese word activities were skipped or refused four times, more than any other activity. That matches his "too heavy" complaint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it still goes wrong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The model sometimes invents details.&lt;/strong&gt; In one test, the activity was "read a few pages of a book", and the 3B model wrote that he should pick up "that book on chess strategies" and flip to page 10. He never said he owns that book. My name check only catches invented capitalized names, so it missed this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It sometimes mixes his interests awkwardly.&lt;/strong&gt; One suggestion was to voice-message a friend "for some lo-fi music chat". Fine, but odd.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A small model on CPU is still slowish.&lt;/strong&gt; A 10-second wait is a real cost when the point is avoiding friction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three come from using a small local model. The rules in Python hold, but the wording still needs closer checks.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Stricter checks on the model's wording, so it can't add things that aren't in the activity.&lt;/li&gt;
&lt;li&gt;A weekly summary that balances moving, creating, connecting, learning and resting.&lt;/li&gt;
&lt;li&gt;A phone-friendly version that still runs locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I built it
&lt;/h2&gt;

&lt;p&gt;I built this with AI-assisted coding (Claude) for the code, and ran, tested and edited it myself. The app itself uses only open-source pieces: Ollama, a Qwen2.5 model, Python and Streamlit.&lt;/p&gt;

&lt;p&gt;If you build something for a friend, ask them what annoys them first. Then watch them use it.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Build for a Friend&lt;/li&gt;
&lt;/ul&gt;

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