<?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: Mattia Petullo</title>
    <description>The latest articles on DEV Community by Mattia Petullo (@tiawrld).</description>
    <link>https://dev.to/tiawrld</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4163576%2Fc3f7d4b9-8362-4ede-9229-b20569c087bd.gif</url>
      <title>DEV Community: Mattia Petullo</title>
      <link>https://dev.to/tiawrld</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tiawrld"/>
    <language>en</language>
    <item>
      <title>GHOST.EXE</title>
      <dc:creator>Mattia Petullo</dc:creator>
      <pubDate>Sat, 31 Oct 2026 17:11:13 +0000</pubDate>
      <link>https://dev.to/tiawrld/ghostexe-33o4</link>
      <guid>https://dev.to/tiawrld/ghostexe-33o4</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;GHOST.EXE&lt;/strong&gt; is a haunting that moves into your computer. There is no app to open and no chat box to talk to. You press "Begin", keep using your PC, and the spirit takes it from there.&lt;/p&gt;

&lt;p&gt;First your screen trembles, lightly. Then a file appears in the middle of your desktop: &lt;code&gt;DON'T OPEN ME&lt;/code&gt;. If you open it, a green-on-black terminal types out your username and tells you it has been waiting for someone. From there, a local open-weight model plays the spirit. It reads real things about your machine (your username, the time, the names of the files on your Desktop, how long you have been idle), remembers what it said, and decides what to do next: speak, shake the screen, drop a new file, move one, make one vanish, or pop up a fake system error styled for your OS.&lt;/p&gt;

&lt;p&gt;A run lasts about 6 to 9 minutes and escalates through five phases: &lt;strong&gt;Omen, Contact, Conversation, Intrusion, Climax and silence&lt;/strong&gt;. It ends with the spirit's last words, written by the model in a completely silent room. If you launch it again later, it greets you before anything else: &lt;em&gt;"you came back. i never left."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I read the theme.&lt;/strong&gt; I took "Ghost in the Machine" literally. The name says it: a program you run, with something already inside. Not a ghost &lt;em&gt;story&lt;/em&gt; generator, but a presence that lives in the machine and acts on your actual desktop while you use it. What unsettles me about haunted-computer stories is never the jump scare, it is the feeling of being watched by something patient. So the spirit is cold, quiet and brief, and the whole demo is short on purpose.&lt;/p&gt;

&lt;p&gt;Three ideas hold it together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The AI is the director, not the only actor.&lt;/strong&gt; The model does not generate effects. It picks from a closed list of hand-built actions (&lt;code&gt;none&lt;/code&gt;, &lt;code&gt;shake&lt;/code&gt;, &lt;code&gt;spawn_file&lt;/code&gt;, &lt;code&gt;spawn_folder&lt;/code&gt;, &lt;code&gt;move_file&lt;/code&gt;, &lt;code&gt;remove_file&lt;/code&gt;, &lt;code&gt;fake_error&lt;/code&gt;) and writes one short line. The effects themselves are polished and safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It really is watching.&lt;/strong&gt; Nothing it says about you is faked. It reads real values, read-only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Breaking expectations.&lt;/strong&gt; If you close the terminal, the spirit does not let it go. About 15 seconds later every sound cuts out, the screen takes a heavy hit, and the terminal reopens by itself: &lt;em&gt;"why did you close it?"&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is harmless by design. It never changes, moves or deletes a real file, never touches your camera or microphone, and starts with a plain-language warning and an emergency exit (Cmd/Ctrl+Shift+Q, or type &lt;code&gt;/exit&lt;/code&gt; in the terminal).&lt;/p&gt;

&lt;p&gt;It is a desktop app (Electron), so there is no live link: it runs on your own machine, with a local model. Three steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull gemma4:e4b
git clone https://github.com/YOUR-USERNAME/ghost-exe &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;ghost-exe &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I developed it on a Mac and tested it on Linux. Windows is untested.&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/TiaWRLD" rel="noopener noreferrer"&gt;
        TiaWRLD
      &lt;/a&gt; / &lt;a href="https://github.com/TiaWRLD/GHOST.EXE" rel="noopener noreferrer"&gt;
        GHOST.EXE
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Hacktoberfest 2026 - Week 4 DEV challenge
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/TiaWRLD/GHOST.EXE" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;The README covers install, the five phases, model choice, fallback, safety, known limits and roadmap.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;The model: Gemma 4 (&lt;code&gt;e4b&lt;/code&gt;), run locally through Ollama.&lt;/strong&gt; The Electron main process is the director: it owns the phase state machine, the spirit's memory and the AI calls. Two renderers do the showing: a transparent, click-through overlay and the fake terminal.&lt;/p&gt;

&lt;p&gt;Each turn calls &lt;code&gt;POST /api/chat&lt;/code&gt; on &lt;code&gt;127.0.0.1&lt;/code&gt;: non-streaming, thinking off, a JSON schema in &lt;code&gt;format&lt;/code&gt; so the reply is &lt;code&gt;{ "say": "...", "action": "..." }&lt;/code&gt; with &lt;code&gt;action&lt;/code&gt; restricted to an enum, temperature 0.8, capped at 120 tokens, model kept loaded for 30 minutes. The app starts loading the model while you read the startup warning, so it is ready by the first omen.&lt;/p&gt;

&lt;p&gt;The prompt is built from: a system prompt (a cold, patient poltergeist that never mentions being an AI), a &lt;strong&gt;phase guide&lt;/strong&gt; (tone and length per phase, for example &lt;em&gt;contact: curious and soft, max 14 words&lt;/em&gt;, &lt;em&gt;intrusion: threatening and clipped&lt;/em&gt;), the &lt;strong&gt;list of actions allowed right now&lt;/strong&gt;, the real facts, the last six memory entries, and the event that just happened. The main process decides what is allowed from the phase and from what is on screen, so the model cannot ask to remove a file that does not exist, and the strongest effects (fake error, vanishing files) only unlock in Intrusion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A small model needs a safety net.&lt;/strong&gt; Every reply is validated. If it is not valid JSON (JSON wrapped in extra text is recovered), breaks character, or repeats an earlier line, it is retried and then replaced by a pre-written line from the same phase. If Ollama is not running or the model is missing, the app detects it at startup and goes straight to those lines. The key moments (greeting, the closed-terminal trick, the staging of the ending) never depend on the model. At exit the app prints how many lines came from the AI and how many from the fallback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything else is hand-built.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The shake takes a screenshot of your screen and jitters it inside the overlay (it falls back to shaking the fake icons if screen capture is not allowed).&lt;/li&gt;
&lt;li&gt;The sound has &lt;strong&gt;no audio files&lt;/strong&gt;. It is all synthesized with the Web Audio API: a drone from three detuned oscillators, a heartbeat that speeds up from about 54 to 118 bpm, whispers made of noise shaped by vowel formants, two-part breaths, glitch clicks fired by every shake, and silence used as an effect.&lt;/li&gt;
&lt;li&gt;The fake error box and the icons are drawn per OS (macOS, Windows, Linux). The icons are original SVG drawings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What went wrong along the way.&lt;/strong&gt; My first whisper sounded like wind and my first breath sounded like a robot. The whisper got fixed by shaping noise with vowel formants, and the breath by splitting it into an inhale and an exhale with irregular airflow flutter.&lt;/p&gt;

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

&lt;p&gt;The spirit only works if it can see &lt;em&gt;you&lt;/em&gt;, and what it sees is personal: your username and the names of the files on your Desktop. Sending that to a cloud API would make the project creepy in the wrong way. With a local model it never leaves the machine, and the README can say so honestly: the app only talks to &lt;code&gt;127.0.0.1&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It works with the lights off.&lt;/strong&gt; Turn Wi-Fi off and nothing changes. A haunting that dies when the connection drops is a bad haunting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing to run.&lt;/strong&gt; No API key, no per-message bill, no rate limit in the middle of a scare. Anyone can clone it and haunt a friend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I get to pin the brain.&lt;/strong&gt; The model is one constant in &lt;code&gt;llm.js&lt;/code&gt;. It cannot be updated, retired or rate-limited under me, and I can swap it for another local model in one line. Structured output with a JSON schema gave me a closed list of actions at the output level, not just a polite request in the prompt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest trade-off: a small local model is sometimes flat or repetitive, so I wrapped it in validation and a fallback and kept the key moments scripted. A bigger closed model might write better lines. It would not let me promise that your Desktop file names stay on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Spirit of It
&lt;/h2&gt;

&lt;p&gt;The first time I ran it with the real model, its replies were more unsettling than I had imagined. [PASTE ONE REAL LINE YOUR SPIRIT SAID, WITH YOUR USERNAME CHANGED]&lt;/p&gt;

&lt;p&gt;The moment I designed the whole project around is a silence. When you close the terminal, nothing happens for fifteen seconds. Then the drone and the heartbeat cut out completely, and for two and a half seconds the room has no sound at all. Then the hit, and the terminal reopens on its own.&lt;/p&gt;

&lt;p&gt;The quietest moment is for the next time you launch it: &lt;em&gt;"you came back. i never left."&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Gemma&lt;/strong&gt;: the spirit's brain is Gemma 4 (&lt;code&gt;e4b&lt;/code&gt;), run locally through Ollama, with schema-constrained JSON output, per-phase prompting and a validation and fallback layer around it.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Echo, a quiet place to think</title>
      <dc:creator>Mattia Petullo</dc:creator>
      <pubDate>Sat, 24 Oct 2026 15:30:01 +0000</pubDate>
      <link>https://dev.to/tiawrld/echo-a-quiet-place-to-think-56a9</link>
      <guid>https://dev.to/tiawrld/echo-a-quiet-place-to-think-56a9</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;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Echo, a quiet place to think&lt;/strong&gt;: a small chatbot that helps you put your thoughts in order. It is not therapy and it does not tell you what to do with your life. It runs &lt;strong&gt;entirely in your browser&lt;/strong&gt; with Gemma 3 1B, so nothing you write is ever uploaded.&lt;/p&gt;

&lt;p&gt;It has four modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vent&lt;/strong&gt;: you write, Echo listens and rephrases what it heard. No advice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reflect&lt;/strong&gt;: four fixed questions, then a hypothesis about an impulse versus an underlying emotion. Never a verdict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unblock&lt;/strong&gt;: you describe a task and what is in the way, and Echo suggests ONE tiny step of 2 to 5 minutes. You can ask for it "even smaller" up to three times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unsent Letter&lt;/strong&gt;: you vent, and Echo rewrites it as a calm letter. It never suggests sending it, and nothing is saved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Who gets to be a little lazier? Anyone who wants to think out loud without creating an account, pasting an API key, or handing a private thought to a server. There is no backend. You open the page, wait for the model to download once, and after that it works offline. And the slow-and-steady part is built in: Unblock only ever asks for the next two-to-five-minute step.&lt;/p&gt;

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

&lt;p&gt;Live: &lt;strong&gt;&lt;a href="https://tiawrld.github.io/echo/" rel="noopener noreferrer"&gt;https://tiawrld.github.io/echo/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need a browser with WebGPU. The first visit downloads the model once (about 859 MB) plus about 27 MB of app files; after that Echo works offline.&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%2Fbmqs87rzk4nvar9ic1w0.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%2Fbmqs87rzk4nvar9ic1w0.png" alt=" " width="800" height="711"&gt;&lt;/a&gt;&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/TiaWRLD" rel="noopener noreferrer"&gt;
        TiaWRLD
      &lt;/a&gt; / &lt;a href="https://github.com/TiaWRLD/echo" rel="noopener noreferrer"&gt;
        echo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Echo, a quiet place to think (Hacktoberfest 2026 week 3 dev challenge)
    &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;Echo, a quiet place to think&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A small, private chatbot that helps you put your thoughts in order
It runs &lt;strong&gt;entirely in your browser&lt;/strong&gt; with Gemma 3 1B: what you write never leaves your device.&lt;/p&gt;
&lt;p&gt;Live: &lt;a href="https://tiawrld.github.io/echo/" rel="nofollow noopener noreferrer"&gt;https://tiawrld.github.io/echo/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Built for Hacktoberfest 2026, week 3 ("build your own chatbot").&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Echo is not therapy, medical advice, or a crisis service.&lt;/strong&gt; It is a tool for reflection
It does not diagnose anything, and its suggestions are hypotheses, never verdicts.
If you are in crisis or thinking about harming yourself, please contact a local helpline: &lt;a href="https://findahelpline.com" rel="nofollow noopener noreferrer"&gt;https://findahelpline.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What it does&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Echo has four modes. In each one, the app's code drives the flow (fixed texts, questions and safeguards); the model only writes a short piece of text.&lt;/p&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;What happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You write, Echo listens and rephrases what it heard. No advice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reflect&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Echo asks four fixed questions, then offers a hypothesis about an impulse versus&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/TiaWRLD/echo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Echo's code is licensed under AGPL-3.0.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: Gemma 3 1B instruct, the ONNX conversion by &lt;code&gt;onnx-community&lt;/code&gt; (q4), run with &lt;strong&gt;Transformers.js v4&lt;/strong&gt; on &lt;strong&gt;WebGPU&lt;/strong&gt; inside a Web Worker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App&lt;/strong&gt;: Nuxt 4 as a static single-page app, Pinia, Tailwind CSS v4 and a PWA service worker. It is deployed to GitHub Pages with GitHub Actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The key design decision&lt;/strong&gt;: a 1B model is small, so I did not let it run the conversation. The code drives the flow (fixed texts, fixed questions, limits like "even smaller, max 3 times"). The model only writes one short thing per step: a rephrase, a hypothesis, a micro-step or a letter. Gemma has no system role, so instructions go in the user turn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety&lt;/strong&gt;: an English keyword check runs before every call to the model, in every mode. If it matches, Echo shows a fixed message with a link to findahelpline.com instead of generating anything. It is deliberately broad, so false alarms can happen, and it only covers English and self-harm language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment detail&lt;/strong&gt;: GitHub Pages serves the app from &lt;code&gt;/echo/&lt;/code&gt;, so the service worker needs the same base path. I added a CI step that fails the build if the worker and the precache do not match it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: I checked privacy in the browser's Network tab (only my own site and huggingface.co appear, and nothing else while chatting), tested offline mode from a fresh tab, and ran Echo on Chrome, Firefox and Safari, on a MacBook and a desktop PC with an RTX 3060.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Working with an AI assistant&lt;/strong&gt;: I built it with Claude as a pair programmer. It wrote and explained code; I ran and tested everything myself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Known limits, also listed in the README: a 1B model can be generic or wrong, the crisis list is English only, and "Stop" in Reflect and Unblock loses your last answer.&lt;/p&gt;

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

&lt;p&gt;With a closed API, every reflection a person writes would travel to someone else's server. An open-weight model that fits in a browser tab made a different promise possible: "nothing you write is uploaded", and you can check it yourself.&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%2Fr3tu9snb5abxgz7dafvl.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%2Fr3tu9snb5abxgz7dafvl.png" alt=" " width="800" height="752"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open code matters for the same reason: the privacy claim is something you can read in the repository, not something you have to trust. I also want to be precise about the word "open". The code is AGPL, but Gemma ships under Google's own Terms of Use and Prohibited Use Policy, so I call it open-weight rather than open source.&lt;/p&gt;

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

&lt;p&gt;Best Use of Gemma&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Archery Tracker</title>
      <dc:creator>Mattia Petullo</dc:creator>
      <pubDate>Sat, 10 Oct 2026 16:57:32 +0000</pubDate>
      <link>https://dev.to/tiawrld/archery-tracker-5gej</link>
      <guid>https://dev.to/tiawrld/archery-tracker-5gej</guid>
      <description>&lt;div class="crayons-card my-2 p-4"&gt;
  &lt;p class="color-base-60"&gt;Post not found or has been removed.&lt;/p&gt;
&lt;/div&gt;
&lt;em&gt;This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass]&lt;/em&gt;
&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Archery Tracker&lt;/strong&gt; is an offline-first mobile app (a PWA) for logging archery training sessions, with an AI coach that comments on your session once you're back home.&lt;/p&gt;

&lt;p&gt;It's built around the way archery actually happens: outdoors, often with poor or no signal, and with your attention on the target rather than on a screen. At the range, the app is a simple, fast scorecard. You log your arrows and everything is saved on your phone. No account, no connection, no AI in the loop. Later, at home, you open a session, tap "Coach", and a local model reads a compact summary of how you shot and replies with a short comment and 2-3 exercises to work on next time.&lt;/p&gt;

&lt;p&gt;A few archery apps have started adding AI feedback, but the ones I found are closed products tied to app stores and accounts. I wanted an open-source alternative where the AI runs on your own machine and your training data stays with you. The screen stays out of the way while you're outside, and the "smart" part waits until you're done and back indoors. It's for hobby and club archers who want to track progress without subscriptions or sending their data anywhere.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

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

&lt;p&gt;The flow in the demo: PWA installed on an Android phone and used at the range with no internet, then, back home, the client computes the session summary and sends it to the backend, and Gemma comments and suggests exercises.&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/TiaWRLD" rel="noopener noreferrer"&gt;
        TiaWRLD
      &lt;/a&gt; / &lt;a href="https://github.com/TiaWRLD/archery-tracker" rel="noopener noreferrer"&gt;
        archery-tracker
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Hacktoberfest 2026 week 1 DEV challenge
    &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;Archery Tracker&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;An offline-first PWA for tracking archery training sessions, with an optional AI coach powered by a local LLM.&lt;/p&gt;
&lt;p&gt;Log your arrows at the range with no signal and no AI involved. Back home, the app summarizes the session and a local model (Gemma, served by Ollama) comments on it and suggests 2-3 exercises. Everything runs on your own machine: no cloud services, no accounts, no data sent to third parties.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it works&lt;/h2&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;At the range (offline).&lt;/strong&gt; The installed PWA records sessions in the browser's IndexedDB. No network is needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At home (online).&lt;/strong&gt; The app computes a compact JSON summary of a session on the client and sends it to the backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The coach.&lt;/strong&gt; The backend prompts a local model through Ollama and returns a short comment plus a few suggested exercises, in the language selected in the app (English or Italian).&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt; Phone (PWA, offline-first)  --JSON summary--&amp;gt;  FastAPI&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/TiaWRLD/archery-tracker" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The repo is a monorepo: &lt;code&gt;frontend/&lt;/code&gt; (the PWA) and &lt;code&gt;backend/&lt;/code&gt; (the FastAPI service that talks to the model), each with its own README.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; Gemma (&lt;code&gt;gemma4:e4b&lt;/code&gt;), served locally with &lt;strong&gt;Ollama&lt;/strong&gt; on a MacBook Air M5.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; a small &lt;strong&gt;FastAPI&lt;/strong&gt; service. It receives the session summary as JSON, builds a prompt, asks Ollama for a comment and a few exercises, and returns them to the app. It reports distinct error cases (model unavailable, bad output, invalid data) so the app can show a useful message instead of a generic failure. I also hardened the prompt and tested it against prompt injection, since free-text notes from the user end up in the model's input (notes are also truncated to 300 characters client-side).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; &lt;strong&gt;Nuxt 3 + Vue&lt;/strong&gt; as a client-only PWA (&lt;code&gt;ssr: false&lt;/code&gt;), with &lt;code&gt;@vite-pwa/nuxt&lt;/code&gt; for the manifest and service worker and &lt;strong&gt;Dexie/IndexedDB&lt;/strong&gt; for local storage. Dark green, mobile-first UI, no external UI libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summary on the client:&lt;/strong&gt; the app computes a compact JSON summary of each session itself, so the model only sees the aggregated data it needs rather than every raw tap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bilingual:&lt;/strong&gt; the interface and the coach's replies work in English and Italian, based on the device language and the user's choice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reaching it from a phone:&lt;/strong&gt; installing a PWA requires HTTPS, so I exposed both the built PWA and the backend from my own machine with &lt;strong&gt;Tailscale Funnel&lt;/strong&gt;, with no hosting service involved. Turning the Funnel off takes one command.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;For this project the privacy and offline story depends on open weights. Training data (how you shoot, your notes, your progress) is personal, and with a local open model it never leaves my machine: there's no API key, no per-request cost, and no third-party server reading it. A closed API would have meant sending every session to someone else's cloud and depending on their pricing, availability and terms.&lt;/p&gt;

&lt;p&gt;It also matters for the app itself. The AI coaches I found for this sport are closed products; an open-source one means archers and clubs can read how the coaching prompt works, change it, and adapt it to their discipline. Swapping in a different Ollama model is a configuration change, not a rewrite. And running the model locally let me iterate on the prompt and test prompt-injection cases as often as I wanted, at no cost.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Gemma&lt;/strong&gt;: Gemma (&lt;code&gt;gemma4:e4b&lt;/code&gt;, running locally through Ollama) is the coach. It reads each session's summary and writes a short, personalised comment plus 2-3 targeted exercises, in the language the user has chosen.&lt;/p&gt;

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