<?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: Achitya Gulati</title>
    <description>The latest articles on DEV Community by Achitya Gulati (@ach0402).</description>
    <link>https://dev.to/ach0402</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F99mvlsfu5tfj9m7ku25d.png</url>
      <title>DEV Community: Achitya Gulati</title>
      <link>https://dev.to/ach0402</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ach0402"/>
    <language>en</language>
    <item>
      <title>Mr. Poodles: I Built a Penguin Companion for a Friend Living in a Hostel</title>
      <dc:creator>Achitya Gulati</dc:creator>
      <pubDate>Sun, 04 Oct 2026 20:14:01 +0000</pubDate>
      <link>https://dev.to/ach0402/mr-poodles-i-built-a-penguin-companion-for-a-friend-living-in-a-hostel-3943</link>
      <guid>https://dev.to/ach0402/mr-poodles-i-built-a-penguin-companion-for-a-friend-living-in-a-hostel-3943</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;When I shared Mr. Poodles with the person I built it for, her feedback began:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's goood&lt;br&gt;&lt;br&gt;
I love how it was made personally for me&lt;br&gt;&lt;br&gt;
The name branding and everything&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That word—&lt;strong&gt;personally&lt;/strong&gt;—is the heart of this project.&lt;/p&gt;

&lt;p&gt;My friend lives in a hostel and has food restrictions. That combination shaped the app: ingredient information matters, available equipment matters, and a useful meal idea has to fit the place where she actually lives.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Mr. Poodles&lt;/strong&gt;, a native Android companion that brings food checks, sourced recipes, calorie logging, meal planning, workouts, and a gentle conversational penguin into one personal space.&lt;/p&gt;

&lt;p&gt;The starting point is four plain-language actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Can I eat this?&lt;/strong&gt; Check pasted ingredients or look up a specific food or product, with conflicts and missing information made visible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find a recipe.&lt;/strong&gt; Retrieve published recipes and check supported results against her restrictions and available equipment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find a workout.&lt;/strong&gt; Find article-supported movements, with instructions and equipment constraints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log what I ate.&lt;/strong&gt; Record food in everyday language, with evidence-based estimates where available and manual corrections when needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Saved recipes feed into planning and shopping. Separate &lt;strong&gt;Hostel&lt;/strong&gt; and &lt;strong&gt;Home&lt;/strong&gt; environments keep their own practical constraints.&lt;/p&gt;

&lt;p&gt;And when she simply wants to talk, Poodles is there too.&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%2Fcyvnjudk4mdekd4zewd9.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%2Fcyvnjudk4mdekd4zewd9.png" alt="Mr. Poodles Home screen with four large pastel task buttons, Talk to Poodles, and today's nourishment summary." width="800" height="1772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Home puts the everyday actions in one place, with clear labels and large controls.&lt;/em&gt;&lt;/p&gt;

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

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

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=xXir_mYY3Mc" rel="noopener noreferrer"&gt;Watch the Android walkthrough on YouTube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This short walkthrough shows Home, companion chat replies, and workout interaction. A beginner-workout request leads to a clarification; a push-up follow-up asks about a suitable wall and clear floor space. The workout detail panel also labels AI programming adjustments separately from article-backed instructions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making it feel like hers
&lt;/h3&gt;

&lt;p&gt;The name, original penguin artwork, and pastel interface are part of the experience. The visual direction draws inspiration from cozy games such as &lt;em&gt;Cats &amp;amp; Soup&lt;/em&gt;; the bundled illustrations and chime are original.&lt;/p&gt;

&lt;p&gt;The same gentle personality runs through companion chat and the food, workout, and logging conversations. Poodles can acknowledge a difficult day without immediately turning it into a lecture. There are no guilt-driven streaks or demands for attention.&lt;/p&gt;

&lt;p&gt;That warmth also needed a usable interface: clear labels, large controls, predictable Back/Home behavior, and drafts that survive navigation. Recipe and workout screens keep the useful context above the conversation, so asking a follow-up doesn't mean losing the result.&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%2Fvkbac99atddsyrrbu6d8.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%2Fvkbac99atddsyrrbu6d8.png" alt="Mr. Poodles launch screen with an illustrated penguin in a pastel room and the tagline a softer little place." width="800" height="1772"&gt;&lt;/a&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%2Fwxb850r7tro1j787et0m.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%2Fwxb850r7tro1j787et0m.png" alt="Companion chat welcome screen saying Come as you are, with the penguin and a bottom message composer." width="800" height="1772"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The launch screen and companion welcome carry the same soft visual identity into the conversation.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What she said
&lt;/h3&gt;

&lt;p&gt;The rest of her feedback was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Especially for someone who has food restrictions and lives in a hostel&lt;br&gt;&lt;br&gt;
It has everything a person would need&lt;br&gt;&lt;br&gt;
From calories to workouts&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Both excerpts preserve her original wording.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is feedback from one person, and that's precisely why it matters to this project. She recognized both the personal touches and the connection between the features.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/achityagulatibvc-bit/Mr.Poodles" rel="noopener noreferrer"&gt;Explore Mr. Poodles on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The original application code is MIT-licensed. Dependencies and hosted models retain their respective licenses. The repository includes setup instructions, tests, third-party notices, and release verification.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Open-weight AI, with application rules around it
&lt;/h3&gt;

&lt;p&gt;The Android client uses &lt;strong&gt;Kotlin and Jetpack Compose&lt;/strong&gt;. A &lt;strong&gt;Cloudflare Worker&lt;/strong&gt; handles hosted inference and research requests.&lt;/p&gt;

&lt;p&gt;The current companion and structured research paths use &lt;strong&gt;Llama 3.1 8B Instruct&lt;/strong&gt; through Cloudflare Workers AI. An optional, separately consented fallback uses &lt;strong&gt;gpt-oss-20b through Groq&lt;/strong&gt;. These are hosted open-weight models; inference does not run on the phone.&lt;/p&gt;

&lt;p&gt;Exa and Tavily provide optional source retrieval. Both inference providers receive the shared Poodles personality and task-specific instructions.&lt;/p&gt;

&lt;p&gt;The research flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Android request + relevant profile constraints
                  |
          Cloudflare Worker
                  |
       Retrieve source material
                  |
   Open-weight model: structured research notes
                  |
       Validate evidence references
                  |
 Android parsers + food/workout-specific checks
                  |
       Display result or uncertainty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model supplies conversational assistance and structured research notes. Application code decides whether the retained evidence is sufficient to construct a supported recipe, workout, or food-log estimate.&lt;/p&gt;

&lt;h3&gt;
  
  
  A friendly answer still needs evidence
&lt;/h3&gt;

&lt;p&gt;One of the most important decisions was how Poodles should behave when information is missing.&lt;/p&gt;

&lt;p&gt;For someone with food restrictions, an incomplete ingredient list cannot quietly become an all-clear. The app distinguishes &lt;strong&gt;Avoid&lt;/strong&gt;, &lt;strong&gt;No listed conflict found&lt;/strong&gt;, and &lt;strong&gt;Need more information&lt;/strong&gt;. Ingredient matching cannot certify food safety.&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%2Flkpv8yo4ypckec5c4qhm.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%2Flkpv8yo4ypckec5c4qhm.png" alt="A mascarpone cheese food check marked Need more information because the complete ingredients and advisory statements are unconfirmed." width="800" height="1772"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The mascarpone check asks for the exact brand, variant, and country. Missing evidence stays visible.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Research claims carry a source ID, a retrieval snapshot ID, and an exact excerpt. Here is part of the actual backend validation in &lt;a href="https://github.com/achityagulatibvc-bit/Mr.Poodles/blob/main/backend/src/research.js" rel="noopener noreferrer"&gt;&lt;code&gt;research.js&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshotId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;invalid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;snapshot_mismatch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;invalid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unknown_source&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;excerpt&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;invalid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;quote_mismatch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nf"&gt;invalid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;quote_not_found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those checks establish where a quote came from. They don't establish that a page is complete or that it describes the correct product. Additional checks handle identity, restrictions, and supported layouts; unresolved gaps stay visible.&lt;/p&gt;

&lt;p&gt;Recipe adaptations are labeled separately from published originals. Unknown nutrition stays unknown. A calorie question does not count as permission to write a diary entry.&lt;/p&gt;

&lt;h3&gt;
  
  
  The bug that taught me to classify failure properly
&lt;/h3&gt;

&lt;p&gt;During development, recipe requests repeatedly showed a source-lookup pause. An unreadable page was being treated like a provider-wide failure, preventing useful candidates from being tried.&lt;/p&gt;

&lt;p&gt;The repair separates &lt;strong&gt;a page we cannot use&lt;/strong&gt; from &lt;strong&gt;a service that is actually rate-limited or unavailable&lt;/strong&gt;. Other candidates can still be tried within the existing request cap, while real cooldowns remain enforced.&lt;/p&gt;

&lt;p&gt;That distinction is small in code and large in the experience: one bad page should not make the whole feature appear unavailable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reliability behind the mascot
&lt;/h3&gt;

&lt;p&gt;Food-log operations use stable operation IDs and persisted results so retries cannot add the same meal twice. Local data uses version-compatible snapshots and atomic replacement; a failed write cannot masquerade as a successful save.&lt;/p&gt;

&lt;p&gt;The recorded 0.4.1 release checks passed &lt;strong&gt;339 Android/JVM/Compose tests and 101 backend tests&lt;/strong&gt;, with zero lint errors. A real Android HTTP transport test rejected an unsupported source and then successfully produced a validated recipe through the deployed backend.&lt;/p&gt;

&lt;p&gt;That live check ran on the build host. Physical-device upgrade and structured usability acceptance for the latest release remain pending; the feedback above is not a substitute for those checks. Details are in the &lt;a href="https://github.com/achityagulatibvc-bit/Mr.Poodles/blob/main/docs/RELEASE_0.4.1.md" rel="noopener noreferrer"&gt;release report&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;A personal app needs to remain adaptable as its person's needs change.&lt;/p&gt;

&lt;p&gt;Open-weight models let this project build around inspectable application behavior and multiple inference options. The current implementation already integrates two different model/provider paths behind the same personality and evidence contract. A future self-hosted deployment is possible engineering work, rather than a promise that this version already runs offline.&lt;/p&gt;

&lt;p&gt;A closed API could generate a friendly reply. The useful difference here is keeping the application's identity, validation rules, and data model separate from any single model service—and publishing the surrounding code so someone else can adapt it for their own friend.&lt;/p&gt;

&lt;p&gt;Cost mattered too. This deployment targets free provider allocations, with bounded requests and an optional fallback. Hosted services still impose quotas; open weights do not make hosting unlimited. Ordinary use doesn't ask my friend to manage API keys.&lt;/p&gt;

&lt;p&gt;Privacy is an explicit application choice: saved chat history and comfort memories have separate opt-ins, memories can be inspected and removed, and unrelated companion history is excluded from research requests. Online inference still sends the relevant request to its provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Community Wisdom
&lt;/h3&gt;

&lt;p&gt;Two DEV posts helped inform the evidence design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/ranknod/check-ai-citations-against-retrieved-source-ids-3hi8"&gt;Check AI Citations Against Retrieved Source IDs&lt;/a&gt; by &lt;strong&gt;Ranknod&lt;/strong&gt;: validate references against the sources supplied for that request.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/enhanciar_ai_96a4ba4877e3/how-we-make-an-llm-cite-every-answer-down-to-fileline-and-check-the-citation-is-telling-the-truth-hmj"&gt;Your AI cited a real file. It still lied to you.&lt;/a&gt; by &lt;strong&gt;Enhanciar&lt;/strong&gt;: a valid citation alone does not prove the adjacent claim.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They informed the approach; the project's own tests and release records describe what this implementation actually verified.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;The next step is watching her complete the everyday flows on the latest build without coaching, then fixing the places where she hesitates. Broader source-layout support also needs more real-world testing.&lt;/p&gt;

&lt;p&gt;Her feedback already gave me a useful direction: keep the personal touches, and keep the everyday needs connected.&lt;/p&gt;

&lt;p&gt;The name made it feel like hers. The engineering has to earn that feeling every time she opens it.&lt;/p&gt;

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