<?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: Shashank Chakraborty</title>
    <description>The latest articles on DEV Community by Shashank Chakraborty (@shashank_chakraborty_6362).</description>
    <link>https://dev.to/shashank_chakraborty_6362</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%2F3704133%2Fd098c3bc-977f-44ec-878c-182cadfbe9d6.jpg</url>
      <title>DEV Community: Shashank Chakraborty</title>
      <link>https://dev.to/shashank_chakraborty_6362</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shashank_chakraborty_6362"/>
    <language>en</language>
    <item>
      <title>TouchGrass AI: I built an outdoor quest app with Ollama and local-first storage</title>
      <dc:creator>Shashank Chakraborty</dc:creator>
      <pubDate>Tue, 06 Oct 2026 21:32:15 +0000</pubDate>
      <link>https://dev.to/shashank_chakraborty_6362/touchgrass-ai-i-built-an-outdoor-quest-app-with-ollama-and-local-first-storage-2c4i</link>
      <guid>https://dev.to/shashank_chakraborty_6362/touchgrass-ai-i-built-an-outdoor-quest-app-with-ollama-and-local-first-storage-2c4i</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;h1&gt;
  
  
  TouchGrass AI: turning an AI prompt into a reason to put my phone away
&lt;/h1&gt;

&lt;p&gt;I built &lt;strong&gt;TouchGrass AI&lt;/strong&gt;, a small outdoor quest companion. You choose how much time you have, what kind of outing sounds good, and how much effort you want. It makes a short quest, then the app gets out of the way so you can go do it.&lt;/p&gt;

&lt;p&gt;The latest test was on my phone: I generated a quest, took a photo for one of its tasks, and the photo stayed available with the saved quest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; &lt;a href="https://github.com/Shashank0701-byte/TouchGrass" rel="noopener noreferrer"&gt;TouchGrass AI on GitHub&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;A quest is a handful of simple prompts for a walk, exploring a familiar area, noticing nature, or taking a photo walk. Tasks can ask for photo evidence. If they do, the task stays incomplete until a photo is saved.&lt;/p&gt;

&lt;p&gt;The app keeps quests, progress, and photo evidence in the browser on that device. Photos are stored as blobs in IndexedDB, can be previewed or removed, and never go into the service worker cache. The app shell can load offline after it has been visited, and a saved quest can go with you when the signal does not.&lt;/p&gt;

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

&lt;p&gt;The UI sends the selected activity, duration, and difficulty to a same-origin server route. That route asks Ollama for structured JSON, then validates the response against the quest rules before showing it. If generation is unavailable or the response is not usable, the route returns a ready-made quest instead.&lt;/p&gt;

&lt;p&gt;For local development I run Ollama on my computer. For the hosted demo I configured Ollama's API with a Gemma model. The API key stays in the server environment; it is not included in browser code.&lt;/p&gt;

&lt;p&gt;The browser stores the quest and its photos locally. In hosted mode, quest-generation settings and the prompt go to Ollama to produce the quest. The app does not ask for or send a location, and the photo evidence is not uploaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open models matter here
&lt;/h2&gt;

&lt;p&gt;I wanted the AI to help create a personal plan, not become the activity itself. Open models let me keep local inference as a real option, change the model, and inspect the boundary between generation and the rest of the app. The hosted API makes the demo accessible without requiring each visitor to install a model, while the offline part of the experience stays useful after a quest is saved.&lt;/p&gt;

&lt;p&gt;That trade-off is deliberate: generation needs a connection in the hosted setup, but the walk, saved tasks, progress, and photo evidence do not depend on a live AI request. A model can suggest the next small thing to notice; it should not need a permanent place in the user's pocket once the walk starts.&lt;/p&gt;

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

&lt;p&gt;The most important boundary was deciding what belongs on the server and what belongs on the phone. The server needs only the choices required to generate a quest. The browser owns the saved quest and evidence. Keeping those responsibilities separate made offline use and photo privacy easier to reason about.&lt;/p&gt;

&lt;p&gt;I also learned that “works on my laptop” is not the finish line for a camera feature. Testing the deployed app on a phone made the whole loop real: take or choose a photo, save it, see it attached to the task, and continue the quest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build session
&lt;/h2&gt;

&lt;p&gt;A lightly edited transcript of the build: practical decisions, one missing persistence bug, and the moment the quests briefly achieved enlightenment by vanishing into tranquility.&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="Codex"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;TouchGrass: when quests vanished into tranquility&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;okay committed and pushed — lets go to the next phase build&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-text"&gt;
                  &lt;p&gt;We moved on to the next phase: keep the quest creation loop useful from first prompt to a saved outing.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;okay generation too and the fallback both working fine but what happens next when i click go back home the quests vanish into tranquility. vanished. not really being saved though ??&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-text"&gt;
                  &lt;p&gt;A peaceful disappearance is charming in poetry and less charming in a quest app. We fixed the home flow so quests are saved locally and show up on the quest shelf after navigation.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;i noticed the icon in this pg is different keep the leaf one i love it&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-text"&gt;
                  &lt;p&gt;The leaf stays. The brand mark was made consistent across the app.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;okay whats next and make it&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-text"&gt;
                  &lt;p&gt;We continued with the next phase, adding photo evidence to tasks that ask for it. Photos are saved on-device in IndexedDB, can be reviewed or removed, and are not cached or uploaded.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;okay i guess all done so can we move towards deployment?&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-text"&gt;
                  &lt;p&gt;We prepared Vercel deployment with server-side Ollama credentials, structured quest validation, and a ready-made fallback if generation fails.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;for this one i used ollama's api key and then used a model used in ollama for gemma i believe&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-text"&gt;
                  &lt;p&gt;We updated the hosted setup to call Ollama's API from the server, so the key stays out of browser code. Gemma can be configured as the hosted model.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&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;worked perfectly in my phone too. the photo clciking is perfect&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-text"&gt;
                  &lt;p&gt;The mobile test confirmed the camera/photo-picker flow works, and the evidence remains attached to the saved quest on that device. The phone has now passed its field test; the app may politely ask it to go outside.&lt;/p&gt;

                &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;
        14 of 14 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Source: &lt;a href="https://github.com/Shashank0701-byte/TouchGrass" rel="noopener noreferrer"&gt;github.com/Shashank0701-byte/TouchGrass&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The hosted demo is deployed on Vercel. &lt;em&gt;(&lt;a href="https://touch-grass-gilt.vercel.app/" rel="noopener noreferrer"&gt;https://touch-grass-gilt.vercel.app/&lt;/a&gt;)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you'd like to run it locally, clone the repository, install Ollama and the configured model, then follow the README setup steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/okoye_ndidiamaka_5e3b7d30/no-internet-your-web-app-should-still-work-offline-functionality-in-pwas-explained-4egg"&gt;No Internet? Your Web App Should Still Work&lt;/a&gt; helped frame the app-shell versus locally saved data distinction.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/pm_cheng_3f36acecfb9c59f5/image-processing-that-never-leaves-your-device-26l6"&gt;Image processing that never leaves your device&lt;/a&gt; is a useful discussion of making on-device data boundaries observable.&lt;/li&gt;
&lt;/ul&gt;




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