<?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: Ray</title>
    <description>The latest articles on DEV Community by Ray (@ray007).</description>
    <link>https://dev.to/ray007</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%2F4167014%2F4b968516-50a1-48d9-bd59-fffaedb5902e.jpg</url>
      <title>DEV Community: Ray</title>
      <link>https://dev.to/ray007</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ray007"/>
    <language>en</language>
    <item>
      <title>Noticed: a quiet photo diary with captions from a local AI</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Sat, 10 Oct 2026 15:47:54 +0000</pubDate>
      <link>https://dev.to/ray007/noticed-a-quiet-photo-diary-with-captions-from-a-local-ai-c1</link>
      <guid>https://dev.to/ray007/noticed-a-quiet-photo-diary-with-captions-from-a-local-ai-c1</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Noticed is a quiet photo diary that runs entirely on your own computer. Once a day you step outside, take one photo of whatever catches your eye, and add it to the app. A local open-source vision model (Gemma 3 through Ollama) writes a one-line caption, and over time you build a gallery of small moments instead of a feed to scroll&lt;/p&gt;

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

&lt;p&gt;Noticed runs locally, so here’s what it looks like.&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%2Fdzkzo9w6grx3ilonn2sk.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%2Fdzkzo9w6grx3ilonn2sk.png" alt="noticed Screenshot" width="799" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can only add one photo per day&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Being-RAYtastic" rel="noopener noreferrer"&gt;
        Being-RAYtastic
      &lt;/a&gt; / &lt;a href="https://github.com/Being-RAYtastic/noticed" rel="noopener noreferrer"&gt;
        noticed
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A private photo diary that captions your daily walk photo with a local open-source AI model (via Ollama).
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Noticed&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Outside for a minute. Noticed for a day.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Noticed is a small photo diary that runs on your own computer. You add a photo from your walk, and a local open-source vision model (Gemma 3 through Ollama) writes a short caption for it.&lt;/p&gt;
&lt;p&gt;Once a day, step outside and take one photo of whatever catches your eye. Noticed keeps it with a short caption, so you build a gallery of small moments instead of a feed to scroll.&lt;/p&gt;
&lt;p&gt;Built for the Hacktoberfest Open-Source AI Challenge, Week 1 ("Touch Grass").&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;TechStack I used:&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; &lt;a href="https://ollama.com/library/gemma3" rel="nofollow noopener noreferrer"&gt;Gemma 3 4B&lt;/a&gt; (open-weight vision model), run locally with &lt;a href="https://ollama.com" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Python, &lt;a href="https://flask.palletsprojects.com" rel="nofollow noopener noreferrer"&gt;Flask&lt;/a&gt; (routes and Jinja templates)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; plain HTML, CSS, and a little JavaScript, with no frameworks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage:&lt;/strong&gt; photos in a folder and entries in a JSON file, with no database&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why it's local&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Photos and captions never leave your computer.&lt;/li&gt;
&lt;li&gt;Location data (EXIF/GPS) is…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Being-RAYtastic/noticed" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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

&lt;h4&gt;
  
  
  TechStack I used:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; &lt;a href="https://ollama.com/library/gemma3" rel="noopener noreferrer"&gt;Gemma 3 4B&lt;/a&gt; (open-weight vision model), run locally with &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Python, Flask (routes and Jinja templates)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; plain HTML, CSS, and a little JavaScript, with no frameworks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage:&lt;/strong&gt; photos in a folder and entries in a JSON file, with no database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Noticed is three small pieces wired together by Flask.&lt;/p&gt;

&lt;p&gt;Noticed is built around one rule: &lt;strong&gt;one photo a day, as a check-in.&lt;/strong&gt; Each day starts with an empty tile for today’s date. Filling it is the whole habit, and once it’s filled the tile disappears until tomorrow. There’s no feed and no upload button to keep tapping, so the diary can only grow by one entry per day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cleaning the photo&lt;/strong&gt;: When you add a photo, Pillow straightens it, shrinks it to at most 2560 px, and saves a fresh JPG with no metadata, so GPS data from the phone never reaches the diary. It also shrinks the image to a single pixel to get its average color, which feeds the strip at the top of the page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Writing the caption&lt;/strong&gt;: The cleaned photo goes to Gemma 3 4B through Ollama, with a short prompt asking for one dreamy or witty line that only mentions what’s visible. A small cleanup step trims the reply, and if the model isn’t running, the entry is still saved with an empty caption instead of crashing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Showing the diary&lt;/strong&gt;: Entries are stored in a plain JSON file and rendered with Jinja templates. There’s no database and no framework on the front end: just HTML, CSS, and a few lines of JavaScript. Today’s upload button is an empty tile at the start of the grid, and it locks while the model works so you can’t send a second photo mid-caption. Each entry shows its date and caption, and the strip of colors at the top turns your days into a quick visual summary.&lt;/p&gt;

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

&lt;p&gt;A diary is about the most personal thing you can build an AI feature for. Photos from your walks show where you go and when, and a caption model has to look at every one of them. That’s why I wanted the model to run on my own machine.&lt;/p&gt;

&lt;p&gt;Because Gemma 3 is open-weight, Noticed can do that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your photos stay with you.&lt;/strong&gt; Captioning happens locally through Ollama, so no photo is uploaded to any service. The app also saves a fresh copy of each photo with its metadata removed, so GPS data from the phone never lands in the diary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No accounts, keys, or per-photo costs.&lt;/strong&gt; One photo a day is a tiny workload, but even tiny workloads cost money on a hosted API and need an account. Here, once the model is downloaded, a caption costs nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MODEL is replaceable.&lt;/strong&gt; The model is a single line in &lt;code&gt;caption.py&lt;/code&gt;. If a better open vision model appears, or you want a different tone for captions, you swap the name and the rest of the app is unchanged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can inspect and fix it.&lt;/strong&gt; When the first small model I tried was too weak for the job, I could try a larger one and tune the prompt myself, rather than being limited to whatever a hosted service decides to offer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Two honest limits:&lt;/strong&gt; the model needs a one-time download, and the page loads its fonts from Google Fonts. Everything else, including your photos and captions, stays on your machine. Captions come from a small 4B model, so they’re sometimes off&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Noticed runs Gemma 3 4B locally through Ollama to write a caption for each day’s photo.&lt;/p&gt;

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