<?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: Jessica Doering</title>
    <description>The latest articles on DEV Community by Jessica Doering (@sizzlebop).</description>
    <link>https://dev.to/sizzlebop</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%2F2676985%2Fa7882ab0-e15a-497b-9151-aeb4899fcc0f.png</url>
      <title>DEV Community: Jessica Doering</title>
      <link>https://dev.to/sizzlebop</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sizzlebop"/>
    <language>en</language>
    <item>
      <title>I Built Mimu Because Even Taking Notes Is Too Much Work</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Sat, 24 Oct 2026 02:35:32 +0000</pubDate>
      <link>https://dev.to/sizzlebop/i-built-mimu-because-even-taking-notes-is-too-much-work-2dg</link>
      <guid>https://dev.to/sizzlebop/i-built-mimu-because-even-taking-notes-is-too-much-work-2dg</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;p&gt;I have a lot of ideas. Sometimes they're useful. Sometimes they're not. And sometimes I think of something I want to remember while I'm doing something completely unrelated.&lt;/p&gt;

&lt;p&gt;The problem is that stopping to organize those thoughts feels like a whole separate task. Give a note a title, decide where it belongs, add tags, maybe set a reminder... suddenly the tiny thought I wanted to save has homework.&lt;/p&gt;

&lt;p&gt;So when this week's challenge asked us to build something that rewards laziness, I knew exactly which chore I wanted to avoid.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Mimu&lt;/strong&gt;, a little voice-note companion that lets me say what's on my mind and get on with my day. The note-taking is my part. The note-organizing is Mimu's.&lt;/p&gt;

&lt;p&gt;And because I wanted to experiment with open models, the AI runs on devices I control rather than through a paid AI API.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Mimu remembers for you.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On my phone, I tap the microphone, ramble for a few seconds, check the transcript, and save it. Whisper transcribes the audio in the browser. Later, a small Gemma model running on my computer turns that raw thought into a note with a useful title, formatted Markdown, a category, and tags.&lt;/p&gt;

&lt;p&gt;The original transcript stays intact, so I can always see what I actually said. And if I don't feel like talking, I can type instead.&lt;/p&gt;

&lt;p&gt;For example, I might say, "I need to call the dentist Thursday at two." Mimu can save that as an organized note with a due date instead of leaving me to remember which of my 47 scattered notes contains the dentist's appointment.&lt;/p&gt;

&lt;p&gt;It also has a few features I added after getting the basic idea working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ask Mimu:&lt;/strong&gt; Ask questions like "Who do I need to call?" and get an answer based on your saved notes, with links to the notes it used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Morning digest and reminders:&lt;/strong&gt; The desktop model prepares a short summary of what's due today and what I saved yesterday. Due-time reminders can be sent to the phone without needing the desktop to stay on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search and editing:&lt;/strong&gt; Find notes by words, categories, and tags, or fix anything yourself without having the model overwrite it later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline capture:&lt;/strong&gt; Notes wait on the phone if the connection drops and sync when it comes back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Markdown export:&lt;/strong&gt; Save one note as &lt;code&gt;.md&lt;/code&gt; or export everything as a ZIP of Markdown files. My notes don't have to live inside Mimu forever.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a responsive web app, so I can capture and browse notes on my phone and work through the library on a bigger screen. I gave it a tiny mascot, too, because apparently I cannot build an app without giving it a face.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Insert mobile screenshots]&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Try Mimu:&lt;/strong&gt; &lt;a href="https://mimu.pinkpixel.dev" rel="noopener noreferrer"&gt;https://mimu.pinkpixel.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I made a hosted demo because I didn't want the first thing a judge had to do to be "create two cloud accounts and configure a database." You can start a demo account or sign in with GitHub and explore sample notes right away.&lt;/p&gt;

&lt;p&gt;To watch your &lt;em&gt;own&lt;/em&gt; notes get organized by AI, you'll need &lt;a href="https://ollama.com/download" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; on a computer. Mimu's Desktop page gives you a command to install and connect the Node worker, which downloads the Gemma model the first time. You can pair your phone by scanning a QR code. The app works as a note library without that worker, but Gemma-powered organizing, Ask, and digests need it running.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/pFlZWNcPq-Y" width="710" height="399"&gt;
  &lt;/iframe&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fdesktop%2F1.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fdesktop%2F1.png" alt="Capture screen with the mic button" width="640" height="340"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fdesktop%2F2.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fdesktop%2F2.png" alt="Typing a note instead of speaking" width="640" height="340"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fdesktop%2F3.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fdesktop%2F3.png" alt="Notes list in the Reminders category with a note open" width="640" height="340"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fdesktop%2F4.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fdesktop%2F4.png" alt="Ask Mimu answering questions about saved notes" width="640" height="340"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F2.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F2.png" alt="Typing a note with Save and Discard buttons" width="292" height="633"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F3.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F3.png" alt="Mimu mascot hugging a note with the message: Got it. I will remember that." width="292" height="633"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F4.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F4.png" alt="Library with search, category filters, the Today digest card, and recent notes with a reminder time" width="292" height="633"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F5.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F5.png" alt="Ask screen with the mascot holding a magnifying glass and a question typed in" width="292" height="633"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F6.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F6.png" alt="Ask screen while Mimu looks through your notes" width="292" height="633"&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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F7.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%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2Fmain%2Fscreenshots%2Fmobile%2F7.png" alt="Ask Mimu answer summarizing the day with links to the source notes" width="292" height="633"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;One important privacy detail: in the hosted demo, note &lt;em&gt;text&lt;/em&gt; is stored in a separate database for each demo account under my Turso setup. Audio isn't uploaded; it's transcribed on the device and discarded. The language model still runs on the user's own computer. Anyone who prefers their own infrastructure can self-host Mimu instead.&lt;/p&gt;

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

&lt;p&gt;The source is available here:&lt;/p&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/pinkpixel-dev" rel="noopener noreferrer"&gt;
        pinkpixel-dev
      &lt;/a&gt; / &lt;a href="https://github.com/pinkpixel-dev/mimu" rel="noopener noreferrer"&gt;
        mimu
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Speak a thought, and a local AI sorts it into searchable Markdown notes.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/assets/icon.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fassets%2Ficon.png" alt="Mimu" width="250" height="250"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Mimu&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Mimu remembers for you.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mimu is a voice notes app for people with too many ideas and not enough patience for note-taking. You tap the mic on your phone, say whatever's on your mind, and it's saved. Later, a model running on your own computer turns those rambling transcripts into tidy Markdown notes with a title, a category, and tags. You can search them, edit them, and export the whole library as plain Markdown whenever you want.&lt;/p&gt;

&lt;p&gt;The speech recognition runs on your phone, and the organizing runs on your desktop. No paid AI API is involved anywhere.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See it in action&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Here's a quick demo video. Click the thumbnail to watch it on YouTube.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://youtu.be/pFlZWNcPq-Y" rel="nofollow noopener noreferrer"&gt;
    &lt;img src="https://camo.githubusercontent.com/c9f8525532802dc01043f69ab1efe5f2b11e424f3ad932229ad5cc3e50c38558/68747470733a2f2f696d672e796f75747562652e636f6d2f76692f70466c5a574e6350712d592f6d617872657364656661756c742e6a7067" alt="Mimu demo video" width="640"&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Desktop&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/desktop/1.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fdesktop%2F1.png" alt="Capture screen with the mic button" width="49%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/desktop/2.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fdesktop%2F2.png" alt="Typing a note instead of speaking" width="49%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/desktop/3.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fdesktop%2F3.png" alt="Notes list in the Reminders category with a note open" width="49%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/desktop/4.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fdesktop%2F4.png" alt="Ask Mimu answering questions about saved notes" width="49%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Mobile&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/mobile/1.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fmobile%2F1.png" alt="Capture screen with the big mic button and a Type instead option" width="23%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/mobile/2.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fmobile%2F2.png" alt="Typing a note with Save and Discard buttons" width="23%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/mobile/3.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fmobile%2F3.png" alt="Mimu mascot hugging a note with the message: Got it. I will remember that." width="23%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/mobile/4.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fmobile%2F4.png" alt="Library with search, category filters, the Today digest card, and recent notes with a reminder time" width="23%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/mobile/5.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fmobile%2F5.png" alt="Ask screen with the mascot holding a magnifying glass and a question typed in" width="23%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/mobile/6.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fmobile%2F6.png" alt="Ask screen while Mimu looks through your notes" width="23%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/mimu/screenshots/mobile/7.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fmimu%2FHEAD%2Fscreenshots%2Fmobile%2F7.png" alt="Ask Mimu answer summarizing the day with links to the source notes" width="23%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Try it&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;There's a hosted demo at &lt;strong&gt;&lt;a href="https://mimu.pinkpixel.dev" rel="nofollow noopener noreferrer"&gt;mimu.pinkpixel.dev&lt;/a&gt;&lt;/strong&gt;, so you don't need a Turso or Cloudflare account to try Mimu.&lt;/p&gt;


&lt;ol&gt;

&lt;li&gt;Open the site and tap &lt;strong&gt;Start a demo&lt;/strong&gt; (or &lt;strong&gt;Continue with&lt;/strong&gt;…&lt;/li&gt;

&lt;/ol&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/pinkpixel-dev/mimu" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;The README includes the setup instructions, architecture, and a quickstart for deploying your own copy.&lt;/p&gt;

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

&lt;p&gt;I started on October 20, which happened to be International Sloth Day. Appropriate timing for an app dedicated to doing less.&lt;/p&gt;

&lt;p&gt;My first plan was a phone app &lt;strong&gt;and&lt;/strong&gt; a separate Tauri desktop app. Then I looked at the deadline and remembered that I am, unfortunately, only one person. I went with one React PWA that works on both screens and a headless Node worker on the desktop. It meant I could spend more of the week making the whole experience actually work, rather than maintaining two UIs.&lt;/p&gt;

&lt;p&gt;The main pieces are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Whisper tiny (English)&lt;/strong&gt; through Transformers.js for speech-to-text in the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 &lt;code&gt;gemma4:e4b&lt;/code&gt;&lt;/strong&gt; through Ollama on my computer for organizing notes, interpreting dates, writing digests, and answering questions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React + Vite&lt;/strong&gt; for the PWA, &lt;strong&gt;Hono on Cloudflare Workers&lt;/strong&gt; for the API, and &lt;strong&gt;Turso/libSQL&lt;/strong&gt; for note storage and full-text search.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Node worker&lt;/strong&gt; that picks up pending jobs, talks to Gemma locally, and sends the results back through the API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The audio is handled on the phone. The saved text travels through the API to the database, and the desktop worker reads that text to process it. So this is &lt;strong&gt;local AI inference&lt;/strong&gt;, not an entirely offline app. I think that distinction matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  The bigger model wasn't better
&lt;/h3&gt;

&lt;p&gt;Before settling on Gemma, I tested three sizes against ten messy sample notes, using structured JSON output through Ollama.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Gemma model&lt;/th&gt;
&lt;th&gt;Valid JSON&lt;/th&gt;
&lt;th&gt;Median time per note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gemma4:e2b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10/10&lt;/td&gt;
&lt;td&gt;3.2s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gemma4:e4b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10/10&lt;/td&gt;
&lt;td&gt;3.4s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gemma4:12b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10/10&lt;/td&gt;
&lt;td&gt;13.7s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The funny thing is that &lt;strong&gt;all three were worse at organizing categories when I gave them a bad instruction&lt;/strong&gt;. I told them to reuse existing categories "even loosely," and suddenly a grocery list was a "General Thought" and a failing CI build belonged with software ideas.&lt;/p&gt;

&lt;p&gt;A much more specific rule about &lt;em&gt;types&lt;/em&gt; of notes fixed the problem. E4B made six sensible categories in that test, without the extra wait from the 12B model. That was a useful reminder that throwing a bigger model at a vague prompt doesn't necessarily fix the prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  My phone had other plans
&lt;/h3&gt;

&lt;p&gt;I initially tried Whisper with WebGPU. It looked promising until I tested it on my iPhone: the model download hit 100%, Safari reloaded, and I got to repeat the whole experience. No visible error. Just goodbye.&lt;/p&gt;

&lt;p&gt;I added little diagnostic breadcrumbs that survived a reload and tracked the crash to ONNX session setup. The browser could detect a WebGPU adapter, but that didn't mean the model could actually run on it.&lt;/p&gt;

&lt;p&gt;Switching to WASM fixed the issue. On the same phone, the model loaded in about &lt;strong&gt;3.3 seconds&lt;/strong&gt; and transcribed a three-second audio clip in about &lt;strong&gt;1.8 seconds&lt;/strong&gt;. For a model this small, WASM was also competitive on my desktop, so I made it the default everywhere.&lt;/p&gt;

&lt;p&gt;I learned more from testing on a real phone than from a lot of happy-path desktop tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  The tricky part wasn't formatting. It was &lt;em&gt;not making things up&lt;/em&gt;.
&lt;/h3&gt;

&lt;p&gt;At one point, Whisper misheard a phrase and Gemma confidently cleaned it up into something that meant the opposite of what I had said. The resulting note looked wonderfully polished. It was also wrong.&lt;/p&gt;

&lt;p&gt;That's a dangerous failure for an app that's supposed to remember things &lt;em&gt;for&lt;/em&gt; me.&lt;/p&gt;

&lt;p&gt;I experimented with ways to make Gemma flag suspicious transcript fragments instead of quietly repairing them. In a small repeated test with deliberately garbled and clean phrases, asking for uncertainty inside the main organizing call caught only some of the errors. Giving uncertainty detection its &lt;strong&gt;own tiny model pass&lt;/strong&gt; caught all ten garbled examples with no false alarms in that test, at roughly &lt;strong&gt;0.6 seconds more per note&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Mimu now has a little &lt;strong&gt;"Mimu wasn't sure about"&lt;/strong&gt; section, and the app verifies that a flagged phrase really appeared in the transcript. It doesn't eliminate every possible transcription error, but it gives me a chance to fix something ambiguous instead of trusting a very convincing invention.&lt;/p&gt;

&lt;h3&gt;
  
  
  I kept giving my lazy app more work
&lt;/h3&gt;

&lt;p&gt;Once the capture-and-organize loop worked, I wanted Mimu to do more than make a neat pile of notes.&lt;/p&gt;

&lt;p&gt;I added natural-language due dates, so "Thursday at two" can become an actual date and time. In my test of 16 phrases run twice, giving Gemma the capture timestamp and timezone produced &lt;strong&gt;32/32 correct date-and-time results&lt;/strong&gt;. Adding a calendar cheat sheet actually made it worse. That one surprised me.&lt;/p&gt;

&lt;p&gt;Then came Ask Mimu, morning digests, and reminders. Ask uses full-text search first, then has Gemma answer from the retrieved notes, with references checked against the notes it received. If the search finds nothing, it says so instead of improvising.&lt;/p&gt;

&lt;p&gt;The final result still has more moving pieces than my original "just let me talk" idea. But they're moving so I don't have to.&lt;/p&gt;

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

&lt;p&gt;Mimu wouldn't be the same project if every voice note had to go through a paid transcription API and every bit of organizing required another hosted model call.&lt;/p&gt;

&lt;p&gt;Using open models let me decide &lt;strong&gt;where the work happens&lt;/strong&gt;. Whisper runs right in the browser, so audio doesn't have to leave the phone. Gemma runs on my own computer through Ollama, so I can experiment with prompts, swap model sizes, and keep using the AI features without paying per note or per question.&lt;/p&gt;

&lt;p&gt;It also meant I could test the model's actual behavior instead of treating it like a mysterious service. I could compare sizes, measure timings, change how uncertainty was handled, and build simple checks around what the model returned.&lt;/p&gt;

&lt;p&gt;There are trade-offs. You need a computer capable of running the model, and some features aren't available until the desktop worker connects. The app also uses cloud storage to sync text between devices, so I'm not claiming the whole system is private-by-default or offline. But the audio stays on the phone, inference happens locally, and you can deploy the app under your own accounts. And your notes can leave as Markdown whenever you want.&lt;/p&gt;

&lt;p&gt;That combination of control, portability, and the freedom to tinker is what made this project exciting to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;I haven't done a formal time-savings study, so I'm not going to pretend Mimu saves an exact number of minutes every day. The benefit I was going for is smaller and more familiar: removing the little bits of friction that make me not bother writing something down at all.&lt;/p&gt;

&lt;p&gt;Instead of stopping to decide on a title, folder, tags, and maybe a reminder, I can just talk. And later, I can search for the thought without remembering how I named it. That's the kind of laziness I can get behind.&lt;/p&gt;

&lt;p&gt;I did test the complete flow with a real phone and laptop: start a demo, connect the worker, pair the phone, speak a note, and watch Gemma organize it. I also tested offline capture and resync. Those aren't hypothetical features in a mockup; they worked in my end-to-end tests.&lt;/p&gt;

&lt;p&gt;The part I still want to keep testing is how well it handles real, everyday notes over time. A clean demo with a few examples is one thing. A growing pile of random thoughts from my brain is an entirely different workload.&lt;/p&gt;

&lt;p&gt;Which, conveniently, I can provide in abundance.&lt;/p&gt;

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

&lt;p&gt;I'm entering &lt;strong&gt;&lt;a href="https://dev.to/challenges/hf26#best-use-of-gemma"&gt;Best Use of Gemma&lt;/a&gt;&lt;/strong&gt;. Gemma 4 is the core of Mimu's note organization, date extraction, question-answering, and digests, running locally through Ollama.&lt;/p&gt;




</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Fixed WebGPU on Linux. Then Forgot How I Did It.</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Wed, 21 Oct 2026 21:13:14 +0000</pubDate>
      <link>https://dev.to/sizzlebop/i-fixed-webgpu-on-linux-then-forgot-how-i-did-it-5hjd</link>
      <guid>https://dev.to/sizzlebop/i-fixed-webgpu-on-linux-then-forgot-how-i-did-it-5hjd</guid>
      <description>&lt;p&gt;I spent a ridiculous amount of time trying to get WebGPU working properly on my Linux machine.&lt;/p&gt;

&lt;p&gt;I eventually figured it out, wrote a script to launch Chrome with all the necessary flags, and even made a desktop launcher so I could just click an icon whenever I wanted to run browser-based AI models.&lt;/p&gt;

&lt;p&gt;Problem solved.&lt;/p&gt;

&lt;p&gt;Except recently, I started thinking about all the trouble I'd gone through and realized something.&lt;/p&gt;

&lt;p&gt;I couldn't remember how I'd fixed it.&lt;/p&gt;

&lt;p&gt;Actually, I couldn't even remember where I'd saved the script.&lt;/p&gt;

&lt;p&gt;So I did what any reasonable developer would do in 2026. I sent an AI agent to search my computer for code I'd written myself.&lt;/p&gt;

&lt;p&gt;And what did it find?&lt;/p&gt;

&lt;p&gt;Not only had I saved the script, I'd also written documentation explaining how it worked and backed everything up in TWO different resource directories.&lt;/p&gt;

&lt;p&gt;Apparently, past me was considerably more organized than present me remembered.&lt;/p&gt;

&lt;p&gt;Anyway, since I've already done all the hard work (and then forgotten about it), I figured I might as well share what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  I just wanted to run AI models in my browser
&lt;/h2&gt;

&lt;p&gt;I've spent quite a bit of time experimenting with local AI models, particularly small language models running through Transformers.js and ONNX Runtime.&lt;/p&gt;

&lt;p&gt;I love the idea of running models directly in the browser. No server to maintain, no API calls to pay for, and inference happens right on your own hardware.&lt;/p&gt;

&lt;p&gt;WebGPU makes a lot of that possible by allowing web applications to use the GPU for computation.&lt;/p&gt;

&lt;p&gt;Which sounds great, right?&lt;/p&gt;

&lt;p&gt;Except my setup wasn't exactly cooperating.&lt;/p&gt;

&lt;p&gt;I'm running Arch-based Linux with Wayland on a laptop with hybrid graphics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intel Raptor Lake UHD integrated graphics&lt;/li&gt;
&lt;li&gt;NVIDIA RTX 4090 Laptop GPU&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And getting Chrome, Vulkan, NVIDIA, and Wayland to play nicely together was an absolute pain.&lt;/p&gt;

&lt;p&gt;There are several layers involved. Your GPU drivers need to work, Vulkan needs to find the right device, Chrome needs to use the right graphics backend, and WebGPU needs to initialize successfully.&lt;/p&gt;

&lt;p&gt;And just because one of those things works doesn't mean the next one will.&lt;/p&gt;

&lt;p&gt;I spent a lot of time troubleshooting different configurations before I finally had something reliable enough to use regularly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution that worked for me
&lt;/h2&gt;

&lt;p&gt;Eventually, I ended up with a Bash script that launches a separate Chrome instance configured specifically for WebGPU.&lt;/p&gt;

&lt;p&gt;Here's the script I recovered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="c"&gt;# Launch Google Chrome with NVIDIA PRIME offload + Vulkan + WebGPU on X11.&lt;/span&gt;
&lt;span class="c"&gt;# Dedicated separate profile so it can run alongside normal Chrome.&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;CHROME_PROFILE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.config/chrome-webgpu-nvidia"&lt;/span&gt;

&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CHROME_PROFILE_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;VK_LOADER_DRIVERS_SELECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'*nvidia*'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;__NV_PRIME_RENDER_OFFLOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;__GLX_VENDOR_LIBRARY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nvidia &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;__VK_LAYER_NV_optimus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NVIDIA_only &lt;span class="se"&gt;\&lt;/span&gt;
google-chrome-stable &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CHROME_PROFILE_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-unsafe-webgpu&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Vulkan &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ozone-platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x11 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not particularly complicated to look at.&lt;/p&gt;

&lt;p&gt;But getting to the point where I knew which settings to use was another story.&lt;/p&gt;

&lt;p&gt;I also created a &lt;code&gt;.desktop&lt;/code&gt; launcher for it, so now when I want to experiment with WebGPU, I can just open that version of Chrome without having to remember any of this.&lt;/p&gt;

&lt;p&gt;Which, as we've established, is probably a good thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What all those settings actually do
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Getting Chrome to use the NVIDIA GPU
&lt;/h3&gt;

&lt;p&gt;My laptop has two GPUs. There's the integrated Intel GPU and the dedicated NVIDIA GPU.&lt;/p&gt;

&lt;p&gt;With hybrid graphics, applications don't necessarily use the GPU you'd expect.&lt;/p&gt;

&lt;p&gt;That's a problem when you're trying to run models on your RTX 4090 and your browser decides the integrated GPU looks perfectly adequate.&lt;/p&gt;

&lt;p&gt;So my script sets four environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;VK_LOADER_DRIVERS_SELECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'*nvidia*'&lt;/span&gt;
&lt;span class="nv"&gt;__NV_PRIME_RENDER_OFFLOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nv"&gt;__GLX_VENDOR_LIBRARY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nvidia
&lt;span class="nv"&gt;__VK_LAYER_NV_optimus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NVIDIA_only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what they're for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;VK_LOADER_DRIVERS_SELECT&lt;/code&gt; filters the Vulkan driver manifests so that the NVIDIA driver is selected.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__NV_PRIME_RENDER_OFFLOAD=1&lt;/code&gt; enables NVIDIA PRIME render offloading.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__GLX_VENDOR_LIBRARY_NAME=nvidia&lt;/code&gt; selects NVIDIA for GLX vendor dispatch.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__VK_LAYER_NV_optimus=NVIDIA_only&lt;/code&gt; tells NVIDIA's Optimus Vulkan layer to expose only the NVIDIA GPU.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not all four variables necessarily matter for every application or graphics path, but this combination was part of my working configuration.&lt;/p&gt;

&lt;p&gt;The important thing was making sure Chrome could actually access and use the GPU I wanted.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Making Wayland cooperate by... not using native Wayland
&lt;/h3&gt;

&lt;p&gt;This one still makes me laugh.&lt;/p&gt;

&lt;p&gt;I'm running a Wayland desktop, but my working Chrome launcher includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--ozone-platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells Chrome to use its X11 backend, which runs through XWayland inside my Wayland session.&lt;/p&gt;

&lt;p&gt;At the time, I was running into problems getting Vulkan and Chrome's native Wayland backend to cooperate with NVIDIA.&lt;/p&gt;

&lt;p&gt;Running Chrome through XWayland was the workaround that finally worked for my setup.&lt;/p&gt;

&lt;p&gt;So after all that effort to get things running properly under Wayland, part of my solution was essentially telling Chrome to pretend it was running under X11.&lt;/p&gt;

&lt;p&gt;Sometimes the practical solution isn't the elegant one.&lt;/p&gt;

&lt;p&gt;It's the one that actually works.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Giving Chrome its own profile
&lt;/h3&gt;

&lt;p&gt;This was one of the more useful discoveries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CHROME_PROFILE_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chrome normally reuses an existing browser instance when you try to launch it again with the same profile.&lt;/p&gt;

&lt;p&gt;So if Chrome is already open and you try launching another window with different GPU flags, you might discover that your new settings aren't actually being applied.&lt;/p&gt;

&lt;p&gt;Using a separate profile directory gives my WebGPU launcher its own Chrome process and GPU configuration.&lt;/p&gt;

&lt;p&gt;That also means I can keep my regular browser open while running a separate instance for development.&lt;/p&gt;

&lt;p&gt;No need to mess with my normal browsing setup every time I want to test something.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Enabling Vulkan and WebGPU
&lt;/h3&gt;

&lt;p&gt;Finally, these two flags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--enable-unsafe-webgpu&lt;/span&gt;
&lt;span class="nt"&gt;--enable-features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Vulkan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first enables experimental WebGPU support and bypasses certain GPU restrictions.&lt;/p&gt;

&lt;p&gt;The second enables Chromium's Vulkan graphics feature.&lt;/p&gt;

&lt;p&gt;There's an important distinction here: enabling Vulkan in Chrome doesn't necessarily guarantee that WebGPU itself is using Vulkan through Dawn, Chromium's WebGPU implementation.&lt;/p&gt;

&lt;p&gt;The exact behavior depends on your Chromium version, platform, and graphics configuration.&lt;/p&gt;

&lt;p&gt;Also, &lt;code&gt;--enable-unsafe-webgpu&lt;/code&gt; is intended for development and testing. It's not something I'd recommend casually enabling in your everyday browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A note about newer Chrome versions:&lt;/strong&gt; WebGPU support on Linux has been improving, so you might not need this exact configuration anymore. In particular, newer releases have expanded support for Intel and NVIDIA hardware. Check your current browser and driver support before copying every flag into your own setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check whether it's actually working
&lt;/h2&gt;

&lt;p&gt;After launching Chrome with the script, open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome://gpu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the Graphics Feature Status section.&lt;/p&gt;

&lt;p&gt;Ideally, you want to see hardware acceleration enabled for WebGPU and Vulkan rather than software fallbacks.&lt;/p&gt;

&lt;p&gt;It's also worth checking the GPU and driver information to make sure Chrome is using the NVIDIA device instead of Intel or a software renderer like SwiftShader.&lt;/p&gt;

&lt;p&gt;But don't stop there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Being able to see WebGPU listed as hardware accelerated doesn't guarantee your actual application will run correctly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Try running a real WebGPU sample or the model you're planning to use.&lt;/p&gt;

&lt;p&gt;I've learned this the hard way more than once.&lt;/p&gt;

&lt;p&gt;For example, while building my recent Mimu note-taking app, Safari on my iPhone reported that WebGPU was available. But attempting to initialize the Whisper model with WebGPU caused the tab to crash and reload.&lt;/p&gt;

&lt;p&gt;The WASM version worked fine.&lt;/p&gt;

&lt;p&gt;And for that particular small model, WASM was fast enough that using WebGPU wasn't worth the trouble anyway.&lt;/p&gt;

&lt;p&gt;That was another useful reminder that the theoretically faster option isn't always the best one.&lt;/p&gt;

&lt;h2&gt;
  
  
  And then I forgot where I put everything
&lt;/h2&gt;

&lt;p&gt;So here's where this whole thing comes full circle.&lt;/p&gt;

&lt;p&gt;Recently, I've started keeping detailed build logs for my projects.&lt;/p&gt;

&lt;p&gt;Not just what I built, but what broke, what I tried, why I made certain decisions, and what I'd do differently if I approached the same problem again.&lt;/p&gt;

&lt;p&gt;Writing more on DEV has actually encouraged this habit. Thinking about what I might eventually write makes me pay more attention to what I'm doing while I'm building.&lt;/p&gt;

&lt;p&gt;And I've already found myself going back through my notes and reconsidering decisions I made just a day or two earlier.&lt;/p&gt;

&lt;p&gt;Which got me thinking about all those earlier experiences with WebGPU.&lt;/p&gt;

&lt;p&gt;I wished I'd documented them better.&lt;/p&gt;

&lt;p&gt;Turns out, I had.&lt;/p&gt;

&lt;p&gt;I just couldn't remember doing it.&lt;/p&gt;

&lt;p&gt;My AI agent found the original launcher in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.local/bin/chrome-webgpu-nvidia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The desktop entry was in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.local/share/applications/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the documentation and additional copies were sitting in my &lt;code&gt;PINKPIXEL/RESOURCES&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;In two different folders.&lt;/p&gt;

&lt;p&gt;I had already done everything I was wishing past me had done.&lt;/p&gt;

&lt;p&gt;I just hadn't done a particularly good job of making that information easy to find again.&lt;/p&gt;

&lt;p&gt;Which is even funnier considering I'm currently building an app designed to help people capture, organize, and remember things.&lt;/p&gt;

&lt;p&gt;Apparently, I really do need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned from all this
&lt;/h2&gt;

&lt;p&gt;The technical lesson here is that getting WebGPU working on Linux can involve more than just enabling a browser flag, especially with hybrid graphics.&lt;/p&gt;

&lt;p&gt;Depending on your hardware and software versions, you may need to pay attention to which GPU is being selected, which graphics backend Chrome is using, and whether your application is actually getting hardware acceleration.&lt;/p&gt;

&lt;p&gt;But I think the bigger lesson for me has less to do with WebGPU.&lt;/p&gt;

&lt;p&gt;I've built a lot of things over the years. I've solved problems, experimented with technologies, and figured out workarounds that took far more effort than I expected.&lt;/p&gt;

&lt;p&gt;And then I moved on to the next interesting thing.&lt;/p&gt;

&lt;p&gt;I didn't always stop to think about what I'd learned or how useful that experience might be later.&lt;/p&gt;

&lt;p&gt;That's something I've been trying to change.&lt;/p&gt;

&lt;p&gt;Keeping build logs has made me more thoughtful about the decisions I'm making, and writing about my experiences has encouraged me to look at them more closely.&lt;/p&gt;

&lt;p&gt;Sometimes that means discovering a better way to approach something.&lt;/p&gt;

&lt;p&gt;Sometimes it means remembering a useful technique.&lt;/p&gt;

&lt;p&gt;And sometimes it means finding out that I already solved a problem, documented it, backed it up twice, and completely forgot about the whole thing.&lt;/p&gt;

&lt;p&gt;At least now I know where my WebGPU script is.&lt;/p&gt;

&lt;p&gt;For the moment, anyway.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>webdev</category>
      <category>ai</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>In Defense of Being a Little Lazy</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Wed, 21 Oct 2026 02:02:53 +0000</pubDate>
      <link>https://dev.to/sizzlebop/in-defense-of-being-a-little-lazy-1cg9</link>
      <guid>https://dev.to/sizzlebop/in-defense-of-being-a-little-lazy-1cg9</guid>
      <description>&lt;p&gt;This week's DEV challenge is about building something that rewards laziness.&lt;/p&gt;

&lt;p&gt;Which did make me laugh a little bit.&lt;/p&gt;

&lt;p&gt;We're usually encouraged to be more productive, work harder, get more done, and make better use of our time. And now here's a challenge asking us to reward people for being lazy.&lt;/p&gt;

&lt;p&gt;But the more I thought about it, the more I started wondering whether laziness is really such a bad thing.&lt;/p&gt;

&lt;p&gt;Because there are different kinds of laziness.&lt;/p&gt;

&lt;p&gt;There's the kind where you avoid doing something you really should be doing. I'm certainly guilty of that sometimes.&lt;/p&gt;

&lt;p&gt;But then there's the kind that makes you look at a tedious, repetitive task and think, there has got to be a better way to do this.&lt;/p&gt;

&lt;p&gt;And I think that second kind deserves a little more credit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sometimes laziness makes us creative
&lt;/h2&gt;

&lt;p&gt;As developers, we do this all the time.&lt;/p&gt;

&lt;p&gt;We'll spend hours building a tool to automate something that probably only takes a few minutes to do manually.&lt;/p&gt;

&lt;p&gt;Does it always make sense? Absolutely not.&lt;/p&gt;

&lt;p&gt;Do we do it anyway? Of course we do.&lt;/p&gt;

&lt;p&gt;But I think there's something valuable in that instinct. It's not necessarily about being unwilling to work. Sometimes it's about being unwilling to keep doing work that doesn't need to exist.&lt;/p&gt;

&lt;p&gt;That kind of laziness can lead to some pretty clever solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  But what about doing nothing?
&lt;/h2&gt;

&lt;p&gt;Here's where I think it gets even more interesting.&lt;/p&gt;

&lt;p&gt;We've gotten so used to measuring everything in terms of productivity that even our free time sometimes feels like it needs a purpose.&lt;/p&gt;

&lt;p&gt;We take breaks so we can come back refreshed and work harder. We track our sleep so we can perform better. We turn hobbies into projects, projects into products, and sometimes products into businesses.&lt;/p&gt;

&lt;p&gt;And there's nothing inherently wrong with any of that.&lt;/p&gt;

&lt;p&gt;But does everything really need to accomplish something?&lt;/p&gt;

&lt;p&gt;What about doing absolutely nothing just because you feel like it?&lt;/p&gt;

&lt;p&gt;Not to recharge. Not to improve your focus. Not because it's part of some carefully planned routine.&lt;/p&gt;

&lt;p&gt;Just because you want to.&lt;/p&gt;

&lt;p&gt;I think there's value in allowing ourselves that kind of freedom, too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maybe it's about choosing where our effort goes
&lt;/h2&gt;

&lt;p&gt;I'm starting to think the good version of laziness isn't really about avoiding effort.&lt;/p&gt;

&lt;p&gt;It's about being more selective with it.&lt;/p&gt;

&lt;p&gt;Sometimes that means finding a smarter way to do something.&lt;/p&gt;

&lt;p&gt;Sometimes it means recognizing that something doesn't need to be done at all.&lt;/p&gt;

&lt;p&gt;And sometimes it means giving yourself permission to spend an afternoon doing something completely unproductive without feeling guilty about it.&lt;/p&gt;

&lt;p&gt;I have been diligently working on my challenge submission, which I suppose is the opposite of being lazy, but the theme for this week got me thinking.&lt;/p&gt;

&lt;p&gt;Maybe laziness has a little more going for it than we give it credit for.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>devjournal</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>What Do You Make When You Can Make Anything?</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Tue, 20 Oct 2026 16:45:47 +0000</pubDate>
      <link>https://dev.to/sizzlebop/what-do-you-make-when-you-can-make-anything-596b</link>
      <guid>https://dev.to/sizzlebop/what-do-you-make-when-you-can-make-anything-596b</guid>
      <description>&lt;p&gt;I have more creative freedom than I've ever had.&lt;/p&gt;

&lt;p&gt;Some days, I have so many ideas that I can't wait to sit down and start building.&lt;/p&gt;

&lt;p&gt;Other days, I open my editor, stare at the empty screen, and can't think of a single thing I want to make.&lt;/p&gt;

&lt;p&gt;It's not because I've run out of possibilities.&lt;/p&gt;

&lt;p&gt;It's because I've got too many.&lt;/p&gt;

&lt;h2&gt;
  
  
  When everything sounds interesting
&lt;/h2&gt;

&lt;p&gt;I've always been someone who likes making things. I get curious about something, start wondering how it works, and before long I'm opening a new project folder.&lt;/p&gt;

&lt;p&gt;Sometimes it's something practical. A tool that solves a problem I've run into, or something I wish existed but haven't been able to find.&lt;/p&gt;

&lt;p&gt;Other times, it's something completely unnecessary that just sounds fun to build.&lt;/p&gt;

&lt;p&gt;And sometimes I don't even care all that much about the finished product. I just want to see if I can make it work.&lt;/p&gt;

&lt;p&gt;That's one of my favorite things about programming. There's always something new to explore, something to figure out, or a random idea that might actually turn into something interesting.&lt;/p&gt;

&lt;p&gt;But there's a downside to being interested in so many things.&lt;/p&gt;

&lt;p&gt;I can sit down with every intention of working on something and find myself mentally bouncing between a dozen different possibilities.&lt;/p&gt;

&lt;p&gt;Maybe I should finish one of my existing projects.&lt;/p&gt;

&lt;p&gt;Maybe I should try that new library I came across yesterday.&lt;/p&gt;

&lt;p&gt;Maybe I should build that little CLI tool I've been thinking about.&lt;/p&gt;

&lt;p&gt;Or maybe I should make something entirely different.&lt;/p&gt;

&lt;p&gt;And somehow, after considering all of those options, I end up doing absolutely none of them.&lt;/p&gt;

&lt;p&gt;Not because I don't want to make something.&lt;/p&gt;

&lt;p&gt;I want to make everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The barriers are disappearing
&lt;/h2&gt;

&lt;p&gt;I think AI has made this feeling even more noticeable for me.&lt;/p&gt;

&lt;p&gt;There was a time when an idea came with a fairly substantial list of things we'd have to figure out before we could even start building it.&lt;/p&gt;

&lt;p&gt;Do we know the language? Could we work with the framework? Would we have to spend weeks learning something new just to get a basic version running?&lt;/p&gt;

&lt;p&gt;Those questions might not necessarily stop us, but they did help narrow down what we were realistically going to attempt.&lt;/p&gt;

&lt;p&gt;Now, a lot of those barriers are smaller.&lt;/p&gt;

&lt;p&gt;I can experiment with a language I'm unfamiliar with, explore a framework I've never used, or take an idea much further than I could have on my own in the same amount of time.&lt;/p&gt;

&lt;p&gt;And I love that.&lt;/p&gt;

&lt;p&gt;I still have plenty to learn, and AI certainly doesn't make the hard parts of building software disappear. But it does make more ideas feel within reach.&lt;/p&gt;

&lt;p&gt;Which means I have fewer reasons to dismiss an idea before I start.&lt;/p&gt;

&lt;p&gt;That sounds great. In theory.&lt;/p&gt;

&lt;p&gt;Most of the time, it is.&lt;/p&gt;

&lt;p&gt;But it also means that almost every passing thought can turn into a potential project.&lt;/p&gt;

&lt;p&gt;And when nearly everything feels possible, choosing what to spend my time on becomes its own challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  I don't think it's always a creative block
&lt;/h2&gt;

&lt;p&gt;I've been thinking about the difference between having no ideas and having too many.&lt;/p&gt;

&lt;p&gt;Because from the outside, they can look exactly the same.&lt;/p&gt;

&lt;p&gt;You sit there staring at an empty editor, not writing a single line of code.&lt;/p&gt;

&lt;p&gt;But what's happening in your head can be completely different.&lt;/p&gt;

&lt;p&gt;Sometimes I genuinely don't feel inspired. Nothing sounds particularly interesting, and I'd rather go do something else.&lt;/p&gt;

&lt;p&gt;Other times, I have so many ideas competing for my attention that I can't settle on one long enough to begin.&lt;/p&gt;

&lt;p&gt;It's almost like standing in front of an enormous menu where everything looks good.&lt;/p&gt;

&lt;p&gt;You'd think having more choices would make the experience better.&lt;/p&gt;

&lt;p&gt;Instead, you spend twenty minutes trying to decide what you want.&lt;/p&gt;

&lt;p&gt;And the funny thing is, I know perfectly well that I don't have to make the best thing.&lt;/p&gt;

&lt;p&gt;I'm not running a company where every project needs a business case. I'm not trying to build the next big startup every time I sit down at my computer.&lt;/p&gt;

&lt;p&gt;Most of the time, I'm just making things because I enjoy making them.&lt;/p&gt;

&lt;p&gt;So why does choosing sometimes feel like such a big decision?&lt;/p&gt;

&lt;h2&gt;
  
  
  The things I could be making
&lt;/h2&gt;

&lt;p&gt;I think part of it is that every project I choose to work on represents a bunch of other projects I'm not choosing.&lt;/p&gt;

&lt;p&gt;If I spend the night working on a terminal app, I'm not experimenting with that interesting new UI framework.&lt;/p&gt;

&lt;p&gt;If I start something new, I'm not finishing something old.&lt;/p&gt;

&lt;p&gt;If I spend three hours exploring an idea that goes nowhere, I could have spent those three hours improving something I already built.&lt;/p&gt;

&lt;p&gt;And yes, I realize how ridiculous that sounds when I'm talking about something I do for fun.&lt;/p&gt;

&lt;p&gt;But I think that's part of what happens when you're curious about a lot of things and have the tools to pursue them.&lt;/p&gt;

&lt;p&gt;You start feeling the weight of all the things you could be doing.&lt;/p&gt;

&lt;p&gt;Even when nobody is asking you to do any of them.&lt;/p&gt;

&lt;p&gt;I also think there's something strangely exciting about an idea before you start building it.&lt;/p&gt;

&lt;p&gt;In your head, it's full of potential. You can imagine what it might become, all the interesting features you could add, and all the things you'll learn along the way.&lt;/p&gt;

&lt;p&gt;Once you actually start, you have to make decisions. You run into limitations. Some parts are less interesting than you expected.&lt;/p&gt;

&lt;p&gt;The idea becomes a real project, with all the ordinary work that comes with one.&lt;/p&gt;

&lt;p&gt;And meanwhile, somewhere in the back of your mind, another shiny idea is waiting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maybe I don't need to make anything
&lt;/h2&gt;

&lt;p&gt;I love that I can sit down at my computer and turn some random thought into something real.&lt;/p&gt;

&lt;p&gt;I love learning new things, trying unfamiliar technologies, and making tools that probably wouldn't exist if I hadn't decided to build them.&lt;/p&gt;

&lt;p&gt;But I'm starting to wonder if I've gotten so used to having something to work on that sitting down without a project feels like a problem I need to solve.&lt;/p&gt;

&lt;p&gt;Maybe not every ounce of free time needs to become a new repository.&lt;/p&gt;

&lt;p&gt;Maybe sometimes I can just explore something without turning it into an application.&lt;/p&gt;

&lt;p&gt;Or spend some time actually using the things I've already made.&lt;/p&gt;

&lt;p&gt;Or close the editor and do something else entirely.&lt;/p&gt;

&lt;p&gt;I don't think the answer is to stop starting projects. Starting things is one of the ways I learn, and honestly, it's a huge part of what makes programming fun for me.&lt;/p&gt;

&lt;p&gt;And I don't think I need to force myself to finish everything I begin, either. Sometimes an experiment has already given me what I wanted from it, even if it never becomes anything more.&lt;/p&gt;

&lt;p&gt;Maybe the harder thing for me to learn is that having the ability to make something doesn't mean I have to.&lt;/p&gt;

&lt;p&gt;That I can have ten ideas and choose just one of them without worrying about the other nine.&lt;/p&gt;

&lt;p&gt;And that sometimes, when nothing feels quite right, I can simply leave the editor closed.&lt;/p&gt;

&lt;p&gt;Because the possibilities aren't going anywhere.&lt;/p&gt;

&lt;p&gt;Maybe having the freedom to make anything also means having the freedom to make nothing.&lt;/p&gt;

</description>
      <category>creativity</category>
      <category>productivity</category>
      <category>devjournal</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Terminal Made Me a Better Developer (And Not for the Reasons I Expected)</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Mon, 19 Oct 2026 00:36:51 +0000</pubDate>
      <link>https://dev.to/sizzlebop/the-terminal-made-me-a-better-developer-and-not-for-the-reasons-i-expected-nn6</link>
      <guid>https://dev.to/sizzlebop/the-terminal-made-me-a-better-developer-and-not-for-the-reasons-i-expected-nn6</guid>
      <description>&lt;p&gt;When I first started using the terminal, sure, it was useful. I could navigate around directories, install packages, run a dev server, do some Git stuff. But most of those things could also be done by clicking a few buttons.&lt;/p&gt;

&lt;p&gt;And clicking buttons seemed perfectly reasonable to me.&lt;/p&gt;

&lt;p&gt;I wasn't really sure about being one of those people who does absolutely everything from a terminal just because I can.&lt;/p&gt;

&lt;p&gt;But the more I got into development, and especially the more time I spent working with Linux, the more I found myself using it.&lt;/p&gt;

&lt;p&gt;Sometimes because it was faster. Sometimes because whatever I was trying to do didn't have a convenient graphical option. And sometimes because I was following instructions and had absolutely no idea what half the commands were doing.&lt;/p&gt;

&lt;p&gt;Eventually, I started getting curious about that last part.&lt;/p&gt;

&lt;p&gt;What was that command actually doing? Why did it work? Why did it fail? And why was I running it in the first place?&lt;/p&gt;

&lt;p&gt;Somewhere along the way, I realized I was learning a lot more than how to use a command line.&lt;/p&gt;

&lt;p&gt;I was starting to understand how things worked underneath all the nice interfaces I'd gotten used to.&lt;/p&gt;

&lt;p&gt;And that's been far more useful than learning to type commands quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  I started paying more attention to the filesystem
&lt;/h2&gt;

&lt;p&gt;I've always understood files and folders. I think most of us have been moving things around in file managers for years without giving it much thought.&lt;/p&gt;

&lt;p&gt;But working in the terminal made me pay attention to things I normally wouldn't have noticed.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;pwd
ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing exciting there, right?&lt;/p&gt;

&lt;p&gt;But when you're working in the terminal, knowing where you are actually matters.&lt;/p&gt;

&lt;p&gt;I've lost count of how many times I've tried running something only to discover I wasn't in the directory I thought I was.&lt;/p&gt;

&lt;p&gt;Or wondered why a configuration file wasn't showing up, only to remember it was hidden.&lt;/p&gt;

&lt;p&gt;Or had something fail because I used a relative path without thinking about what it was relative &lt;em&gt;to&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;These are pretty basic things, but they're also things I could get away with not thinking about when I was just clicking through folders.&lt;/p&gt;

&lt;p&gt;I started paying more attention to hidden files, symbolic links, absolute versus relative paths, and where applications store their configuration.&lt;/p&gt;

&lt;p&gt;And suddenly, a bunch of little things that used to confuse me started making more sense.&lt;/p&gt;

&lt;p&gt;Not because the terminal magically made me smarter. I just had to understand what I was doing instead of relying on an interface to handle it for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  I finally started understanding processes
&lt;/h2&gt;

&lt;p&gt;This was a big one for me.&lt;/p&gt;

&lt;p&gt;When you open an application normally, you click an icon and it opens. When you're finished, you close it.&lt;/p&gt;

&lt;p&gt;Simple enough.&lt;/p&gt;

&lt;p&gt;But there's a lot going on behind that, and I didn't always give it much thought.&lt;/p&gt;

&lt;p&gt;Running things from the terminal made processes a lot more visible.&lt;/p&gt;

&lt;p&gt;Especially when working on web apps.&lt;/p&gt;

&lt;p&gt;If you've spent any time developing with Vite, you've probably encountered the dreaded port-already-in-use situation.&lt;/p&gt;

&lt;p&gt;You try to start your dev server, and something is already sitting on the port you wanted.&lt;/p&gt;

&lt;p&gt;Sometimes it's another instance of your app that you forgot was still running. Ask me how I know.&lt;/p&gt;

&lt;p&gt;Instead of just closing random terminal windows and hoping for the best, I started learning how to see what was actually running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ps aux
pgrep &lt;span class="nt"&gt;-af&lt;/span&gt; node
ss &lt;span class="nt"&gt;-ltnp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if I specifically want to know what's listening on port 5173:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ss &lt;span class="nt"&gt;-ltnp&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;':5173'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands let me investigate the processes and listening sockets on my system. Depending on permissions, I might not be able to see every process associated with a socket, but it's a useful place to start.&lt;/p&gt;

&lt;p&gt;It seems like a small thing, but understanding the relationship between a running application, its process, and the port it's using helped a lot of other concepts click for me.&lt;/p&gt;

&lt;p&gt;Before, I knew my dev server was running because the browser showed my app.&lt;/p&gt;

&lt;p&gt;Now I had a better idea of what &lt;em&gt;running&lt;/em&gt; actually meant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permissions started making a lot more sense
&lt;/h2&gt;

&lt;p&gt;Linux permissions were another one of those things I sort of understood in theory.&lt;/p&gt;

&lt;p&gt;Read, write, execute. Got it.&lt;/p&gt;

&lt;p&gt;Except apparently I didn't always get it, because I'd still run into situations where I couldn't modify a file or execute a script and wonder what the hell was going on.&lt;/p&gt;

&lt;p&gt;The terminal made it easier to actually look at what was happening.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; script.sh
&lt;span class="nb"&gt;stat &lt;/span&gt;script.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of just getting a permission-denied message and being annoyed about it, I could check who owned the file and what permissions it had.&lt;/p&gt;

&lt;p&gt;I started understanding why a file might be readable but not writable, or why a script wouldn't execute even though it was sitting right there.&lt;/p&gt;

&lt;p&gt;I also learned that execute permission on a directory doesn't mean quite the same thing as execute permission on a file. On a directory, it's about being able to traverse it.&lt;/p&gt;

&lt;p&gt;That's one of those little Linux details that seems weird until you understand it.&lt;/p&gt;

&lt;p&gt;And then there's &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I think it's pretty easy when you're learning Linux to see a permission error and think, well, I'll just stick sudo in front of it.&lt;/p&gt;

&lt;p&gt;Problem solved!&lt;/p&gt;

&lt;p&gt;Except maybe not.&lt;/p&gt;

&lt;p&gt;You might get the command to work, but you still don't know why it needed elevated permissions. And depending on what you're doing, you might end up creating files owned by root that really shouldn't be.&lt;/p&gt;

&lt;p&gt;I've learned that getting something to work and understanding why it wasn't working are two very different things.&lt;/p&gt;

&lt;p&gt;That lesson has come up quite a bit in development, actually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Networking became a little less mysterious
&lt;/h2&gt;

&lt;p&gt;Networking is one of those subjects where I understood the general concepts long before I felt comfortable troubleshooting anything.&lt;/p&gt;

&lt;p&gt;I knew what DNS was. I knew what ports were. I understood that applications communicate over networks.&lt;/p&gt;

&lt;p&gt;Great.&lt;/p&gt;

&lt;p&gt;But when something wouldn't connect, that knowledge didn't necessarily tell me where to start.&lt;/p&gt;

&lt;p&gt;Was the hostname resolving? Was the server actually responding? Was my application even listening on the port I thought it was?&lt;/p&gt;

&lt;p&gt;Or had I somehow managed to break something entirely unrelated?&lt;/p&gt;

&lt;p&gt;The terminal gave me a way to start narrowing those things down.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig example.com
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://example.com
ss &lt;span class="nt"&gt;-ltn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands look at different pieces of the puzzle.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dig&lt;/code&gt; lets me check DNS resolution.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl&lt;/code&gt; lets me make an HTTP request and inspect the response.&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;ss&lt;/code&gt; lets me see which TCP ports are listening on my own system.&lt;/p&gt;

&lt;p&gt;None of these commands will magically explain every network problem, obviously. But they give me somewhere to start.&lt;/p&gt;

&lt;p&gt;And I think that's what made the biggest difference.&lt;/p&gt;

&lt;p&gt;I stopped treating every connection failure as one big mysterious problem and started trying to figure out which part was actually failing.&lt;/p&gt;

&lt;p&gt;Because "my app can't connect" could mean quite a few different things.&lt;/p&gt;

&lt;p&gt;And knowing which one you're dealing with makes troubleshooting a whole lot easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  I got better at actually reading errors
&lt;/h2&gt;

&lt;p&gt;This might sound ridiculous, but I think one of the most useful things I've learned from working in the terminal is to actually read what my tools are telling me.&lt;/p&gt;

&lt;p&gt;Not just glance at the error, decide something is broken, and immediately start trying things until it works.&lt;/p&gt;

&lt;p&gt;I mean &lt;em&gt;really&lt;/em&gt; read it.&lt;/p&gt;

&lt;p&gt;When you're working in the terminal, you see a lot of output.&lt;/p&gt;

&lt;p&gt;Compiler errors, dependency warnings, stack traces, server logs, and sometimes an absolutely ridiculous wall of text because one little thing went wrong.&lt;/p&gt;

&lt;p&gt;At first, all that output can be overwhelming.&lt;/p&gt;

&lt;p&gt;And sometimes it still is.&lt;/p&gt;

&lt;p&gt;But the more I worked with it, the more I started recognizing what was worth paying attention to.&lt;/p&gt;

&lt;p&gt;A missing environment variable isn't the same thing as a network request failing.&lt;/p&gt;

&lt;p&gt;A dependency conflict isn't a syntax error.&lt;/p&gt;

&lt;p&gt;And an application that crashes immediately is a very different problem from one that's running perfectly fine but not responding the way you expected.&lt;/p&gt;

&lt;p&gt;I still have plenty of moments where I stare at an error wondering what on earth it's trying to tell me.&lt;/p&gt;

&lt;p&gt;But I'm much more likely now to investigate the actual error instead of immediately throwing another possible solution at it.&lt;/p&gt;

&lt;p&gt;And when I do have to look something up, I usually have a much better idea of &lt;em&gt;what&lt;/em&gt; I need to look up.&lt;/p&gt;

&lt;p&gt;That's made a pretty big difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real benefit has been learning how to investigate things
&lt;/h2&gt;

&lt;p&gt;I think this is the part I didn't expect when I started using the terminal more.&lt;/p&gt;

&lt;p&gt;I thought I'd learn some useful commands. Maybe speed up a few workflows.&lt;/p&gt;

&lt;p&gt;What I didn't expect was how much it would change the way I approached problems.&lt;/p&gt;

&lt;p&gt;Now, when something doesn't work, I'm more likely to start asking questions.&lt;/p&gt;

&lt;p&gt;Where is this command actually running?&lt;/p&gt;

&lt;p&gt;What process is using that port?&lt;/p&gt;

&lt;p&gt;Who owns this file?&lt;/p&gt;

&lt;p&gt;Is the server responding at all?&lt;/p&gt;

&lt;p&gt;What does the error message actually say?&lt;/p&gt;

&lt;p&gt;And I don't mean that I always know how to figure these things out.&lt;/p&gt;

&lt;p&gt;Far from it.&lt;/p&gt;

&lt;p&gt;Half the time I'm still looking up commands, reading documentation, or finding out that the thing I &lt;em&gt;thought&lt;/em&gt; I understood works a little differently than I expected.&lt;/p&gt;

&lt;p&gt;But that's kind of the point.&lt;/p&gt;

&lt;p&gt;I don't think being comfortable with the terminal means memorizing hundreds of commands or being able to type some ridiculous one-liner from memory.&lt;/p&gt;

&lt;p&gt;It means knowing that there's probably a way to investigate what's happening, and being willing to figure out how.&lt;/p&gt;

&lt;p&gt;Sometimes that means using a command I already know.&lt;/p&gt;

&lt;p&gt;Sometimes it means spending twenty minutes reading documentation to figure out why that command didn't do what I expected.&lt;/p&gt;

&lt;p&gt;Both are useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things worth experimenting with
&lt;/h2&gt;

&lt;p&gt;If you're relatively new to the terminal, or you've mostly been using it to install packages and start development servers, here are a few little exercises worth trying.&lt;/p&gt;

&lt;p&gt;These examples are mostly aimed at Linux, since that's what I use. Some commands will be different on macOS or Windows.&lt;/p&gt;

&lt;p&gt;The goal isn't to memorize them. It's to look at what they show you and try to understand why that information matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Take a closer look at a project directory
&lt;/h3&gt;

&lt;p&gt;Open a terminal inside one of your projects and try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;pwd
ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-maxdepth&lt;/span&gt; 2 &lt;span class="nt"&gt;-type&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at where you are, which files are hidden, and how things are organized.&lt;/p&gt;

&lt;p&gt;Try running the commands from different directories and see what changes.&lt;/p&gt;

&lt;p&gt;Pay particular attention to relative paths. They're simple until they're the reason something isn't working.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Find your development server
&lt;/h3&gt;

&lt;p&gt;Start a development server like you normally would.&lt;/p&gt;

&lt;p&gt;Then open another terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pgrep &lt;span class="nt"&gt;-af&lt;/span&gt; node
ss &lt;span class="nt"&gt;-ltnp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using a Node-based development server on Linux, see if you can find its process and the port it's listening on.&lt;/p&gt;

&lt;p&gt;If you can't see the process information you expected, look into why. It might be a permissions issue, or your server might be running through a different executable.&lt;/p&gt;

&lt;p&gt;The investigation is the exercise.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Look at file permissions
&lt;/h3&gt;

&lt;p&gt;Pick a file in your project and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; package.json
&lt;span class="nb"&gt;stat &lt;/span&gt;package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What do all those permission bits mean?&lt;/p&gt;

&lt;p&gt;Who owns the file?&lt;/p&gt;

&lt;p&gt;What can the owner do that other users might not be able to?&lt;/p&gt;

&lt;p&gt;You don't need to go changing permissions just to experiment. In fact, I'd recommend understanding what you're looking at before doing that.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. See what happens during an HTTP request
&lt;/h3&gt;

&lt;p&gt;Try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's quite a bit of information in that output.&lt;/p&gt;

&lt;p&gt;Look at the connection details, TLS negotiation, request headers, and response headers.&lt;/p&gt;

&lt;p&gt;You don't need to understand every line right away.&lt;/p&gt;

&lt;p&gt;Pick something unfamiliar and look it up.&lt;/p&gt;

&lt;p&gt;That's literally how I've learned a lot of this stuff.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Experiment with pipes
&lt;/h3&gt;

&lt;p&gt;Here's a tiny one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'apple\nbanana\napricot\n'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'^a'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apple
apricot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That little &lt;code&gt;|&lt;/code&gt; sends the output of one command into another command.&lt;/p&gt;

&lt;p&gt;It's such a simple idea, but it's also one of the things that makes Unix-like command-line environments so useful.&lt;/p&gt;

&lt;p&gt;Instead of needing one giant tool that does everything, you can connect smaller tools together.&lt;/p&gt;

&lt;p&gt;Once that concept clicks, a lot of terminal workflows start making more sense.&lt;/p&gt;

&lt;p&gt;And it's worth experimenting with beyond this little example.&lt;/p&gt;

&lt;h2&gt;
  
  
  You don't have to do everything in the terminal
&lt;/h2&gt;

&lt;p&gt;I should probably mention this because I know how these conversations sometimes go.&lt;/p&gt;

&lt;p&gt;I am not suggesting everyone should abandon graphical applications and spend the rest of their lives staring at a terminal window.&lt;/p&gt;

&lt;p&gt;I use graphical applications all the time.&lt;/p&gt;

&lt;p&gt;There are plenty of things I'd rather do with a good interface, and I'm not going to make my life unnecessarily complicated just to prove I can do something from the command line.&lt;/p&gt;

&lt;p&gt;I also don't think using a terminal automatically makes someone a better developer.&lt;/p&gt;

&lt;p&gt;You can copy and paste commands all day without understanding a single thing about what they do. Just like you can click around a graphical interface without really knowing what's happening.&lt;/p&gt;

&lt;p&gt;The difference, at least for me, has been curiosity.&lt;/p&gt;

&lt;p&gt;When I started paying attention to what commands were doing, why they were working, and why they occasionally failed spectacularly, I started learning a lot more.&lt;/p&gt;

&lt;p&gt;The terminal just makes it particularly easy to see some of the things that graphical interfaces usually handle for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not really about typing faster
&lt;/h2&gt;

&lt;p&gt;I started using the terminal because it was useful.&lt;/p&gt;

&lt;p&gt;And sure, I've gotten faster at certain things. There are plenty of tasks where opening a terminal and typing a command is easier than clicking through a bunch of menus.&lt;/p&gt;

&lt;p&gt;But that hasn't been the most valuable part.&lt;/p&gt;

&lt;p&gt;What's really changed is how I see the software I'm working with.&lt;/p&gt;

&lt;p&gt;An application isn't just something that opens when I click an icon anymore. There are processes running, files being accessed, permissions being checked, network connections being made, and all kinds of smaller things happening behind the scenes.&lt;/p&gt;

&lt;p&gt;And when something goes wrong, I have a much better idea of where to start looking.&lt;/p&gt;

&lt;p&gt;I still have a ridiculous amount to learn. I look things up constantly, experiment with things I don't fully understand yet, and occasionally break something because I was a little too confident.&lt;/p&gt;

&lt;p&gt;But I'm getting better at figuring things out.&lt;/p&gt;

&lt;p&gt;And that's what working in the terminal has really helped me with.&lt;/p&gt;

&lt;p&gt;Not becoming some command-line expert.&lt;/p&gt;

&lt;p&gt;Just becoming a better investigator.&lt;/p&gt;

&lt;p&gt;Which, the more I learn about development, the more I realize is a pretty important skill.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>linux</category>
      <category>beginners</category>
      <category>terminal</category>
    </item>
    <item>
      <title>I Built a New Tab Extension for DEV</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Sun, 18 Oct 2026 17:13:41 +0000</pubDate>
      <link>https://dev.to/sizzlebop/i-built-a-new-tab-extension-for-dev-4kmm</link>
      <guid>https://dev.to/sizzlebop/i-built-a-new-tab-extension-for-dev-4kmm</guid>
      <description>&lt;p&gt;I spend a lot of time on DEV these days. Reading posts, finding interesting projects, participating in challenges, and occasionally writing something myself.&lt;/p&gt;

&lt;p&gt;I also like daily.dev. Having a feed of developer content right there whenever I open a new tab is pretty convenient.&lt;/p&gt;

&lt;p&gt;So naturally, I started thinking... what if I had something like that, but just for DEV?&lt;/p&gt;

&lt;p&gt;And because apparently I can't have an idea without turning it into another project, I built one.&lt;/p&gt;

&lt;p&gt;It's called &lt;strong&gt;DEV Tab&lt;/strong&gt;, and it's a free, open-source browser extension that replaces your new tab page with a feed of posts from DEV.&lt;/p&gt;

&lt;p&gt;It's now available on the Chrome Web Store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://chromewebstore.google.com/detail/dev-tab/mfhbilfjgklgebkclbkabohhkibomnop" rel="noopener noreferrer"&gt;Install DEV Tab for Chrome&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Firefox support is built too, and the add-on is currently awaiting review. I'll update this post with the link once it's approved.&lt;/p&gt;

&lt;p&gt;Firefox was approved!&lt;br&gt;
&lt;strong&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/dev-tab/" rel="noopener noreferrer"&gt;Install for Firefox&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A little more than just a feed
&lt;/h2&gt;

&lt;p&gt;The original idea was pretty simple. Open a new tab, see what's happening on DEV, and click through to anything interesting.&lt;/p&gt;

&lt;p&gt;But, as usual, I kept thinking of things to add.&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%2Fv4b1vtesc6c1jslog8gz.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%2Fv4b1vtesc6c1jslog8gz.png" alt="DEV Tab showing a grid of DEV posts" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can browse posts from Today, This Week, Rising, and Latest, along with dedicated sections for trends, events, podcasts, and videos.&lt;/p&gt;

&lt;p&gt;There are also tag filters, so you can quickly jump between subjects you're interested in. You can save your favorite tags, hide tags you'd rather not see, and follow posts from specific DEV organizations.&lt;/p&gt;

&lt;p&gt;A few other things I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search directly from the new tab page.&lt;/li&gt;
&lt;li&gt;Keyboard navigation using arrow keys and Enter.&lt;/li&gt;
&lt;li&gt;A compact view if you'd rather see more posts and fewer images.&lt;/li&gt;
&lt;li&gt;Reaction counts and previews of the three newest comments.&lt;/li&gt;
&lt;li&gt;A shortcut to create a new DEV post.&lt;/li&gt;
&lt;li&gt;Feed caching, so opening a new tab doesn't mean waiting for everything to load again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing particularly revolutionary here. I just wanted a convenient way to explore DEV without having to go looking for things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then I decided it needed a dashboard
&lt;/h2&gt;

&lt;p&gt;This part wasn't in my original plan, but I spend enough time writing on DEV that I thought having a better overview of my own activity would be useful.&lt;/p&gt;

&lt;p&gt;If you add your DEV API key in the extension settings, you unlock some additional features, including a personal dashboard.&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%2Fc5r6ncbj958xadwwbhgg.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%2Fc5r6ncbj958xadwwbhgg.png" alt="DEV Tab dashboard with example statistics, charts, and post activity" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The dashboard includes your follower count, views, reactions, comments, and new followers, with options to look at the last 7, 30, or 90 days.&lt;/p&gt;

&lt;p&gt;There's also a daily views chart, an activity heatmap that lets you browse previous years, and a list of your published posts and drafts.&lt;/p&gt;

&lt;p&gt;You can see recent followers, top supporters, and where your readers are coming from, too.&lt;/p&gt;

&lt;p&gt;I particularly like having the activity heatmap and post statistics together. It's interesting to look back and see when I was active and how different posts performed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The dashboard screenshot above uses fictional example data, by the way.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting your DEV account is completely optional
&lt;/h2&gt;

&lt;p&gt;You don't need an account or API key to use the extension. The public feeds, search, filters, and other browsing features work without one.&lt;/p&gt;

&lt;p&gt;But if you do connect your DEV account, you also get access to your personal feed based on the tags you follow, your reading list, and semantic search.&lt;/p&gt;

&lt;p&gt;You can generate an API key from your &lt;a href="https://dev.to/settings/extensions"&gt;DEV settings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The extension doesn't have a backend, analytics, or tracking. Your API key stays in your browser's local extension storage and is only sent to DEV for authenticated API requests.&lt;/p&gt;

&lt;p&gt;I wanted to keep it simple and avoid introducing a separate service just to display information DEV already makes available.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few limitations
&lt;/h2&gt;

&lt;p&gt;There are a couple of things I would have liked to include but couldn't because of the DEV API.&lt;/p&gt;

&lt;p&gt;For example, you can't directly react to posts, leave comments, or save articles to your reading list from the extension.&lt;/p&gt;

&lt;p&gt;You can view reaction counts and preview comments, but interacting with a post opens it on DEV itself.&lt;/p&gt;

&lt;p&gt;I'd love to have those actions directly in the feed someday, but for now, that's a limitation of what's available through the API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built with WXT, React, and TypeScript
&lt;/h2&gt;

&lt;p&gt;I used &lt;a href="https://wxt.dev/" rel="noopener noreferrer"&gt;WXT&lt;/a&gt; for the extension framework, along with React and TypeScript.&lt;/p&gt;

&lt;p&gt;This was my first time using WXT, and I really liked being able to build for Chrome and Firefox from the same codebase.&lt;/p&gt;

&lt;p&gt;One thing I spent some time on was making sure the feed wouldn't constantly refetch everything whenever a new tab opened. The first page of each feed gets cached for ten minutes, and previously loaded posts can still appear if you're offline.&lt;/p&gt;

&lt;p&gt;It's a small thing, but when you're replacing something as frequently used as the new tab page, I think it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give it a try!
&lt;/h2&gt;

&lt;p&gt;DEV Tab is open source, so you can take a look at the code, report bugs, suggest features, or contribute if you'd like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://chromewebstore.google.com/detail/dev-tab/mfhbilfjgklgebkclbkabohhkibomnop" rel="noopener noreferrer"&gt;Chrome Web Store&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/pinkpixel-dev/DEV-tab" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Firefox version is currently awaiting approval, and I'll add the link here when it's published.&lt;/p&gt;

&lt;p&gt;This started as one of those little "wouldn't it be nice if..." ideas, and somehow turned into a full browser extension with a personal analytics dashboard.&lt;/p&gt;

&lt;p&gt;I guess that's what happens when you keep finding things you want to build.&lt;/p&gt;

&lt;p&gt;If you use DEV regularly, I'd love to hear what you think! And if there's something you'd find useful in a future version, let me know.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What I Actually Learn When I Build With AI</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Fri, 16 Oct 2026 01:06:09 +0000</pubDate>
      <link>https://dev.to/sizzlebop/what-i-actually-learn-when-i-build-with-ai-1074</link>
      <guid>https://dev.to/sizzlebop/what-i-actually-learn-when-i-build-with-ai-1074</guid>
      <description>&lt;p&gt;I've spent entire nights building something with AI, gotten a bunch of features working, and then realized I couldn't really explain half of what I'd just built.&lt;/p&gt;

&lt;p&gt;And then there are nights when I spend hours trying to figure out one stupid little problem, and somehow end up learning more from that than I did from the entire night before.&lt;/p&gt;

&lt;p&gt;It's kind of funny when you think about it. Both times I was productive. Both times I ended up with working code. But what I actually learned from each experience was completely different.&lt;/p&gt;

&lt;p&gt;I wrote a post recently about how AI is making it way too easy to avoid thinking, and it got me thinking about my own habits. Because I use AI coding tools constantly. I love them. They've helped me build things I probably wouldn't have even attempted otherwise.&lt;/p&gt;

&lt;p&gt;But I'm also still learning. A lot.&lt;/p&gt;

&lt;p&gt;And there is a big difference between just getting something working and actually understanding how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Just because I understand the explanation doesn't mean I understand the code
&lt;/h2&gt;

&lt;p&gt;This probably happens to all of us more than we'd like to admit.&lt;/p&gt;

&lt;p&gt;I might ask AI to explain something, and it'll give me a perfectly reasonable breakdown. Everything makes sense. I can follow along, I understand what each part is doing, and I think, okay, got it.&lt;/p&gt;

&lt;p&gt;Then 3 days later I need to change something, and suddenly I'm staring at the code like I've never seen it before.&lt;/p&gt;

&lt;p&gt;Apparently, I understood it just fine when someone was holding my hand through the entire explanation. &lt;/p&gt;

&lt;p&gt;That is not quite the same thing as actually knowing it, though.&lt;/p&gt;

&lt;p&gt;And I'm not talking about memorizing syntax or remembering every little API detail. I look things up all the time, and I don't see anything wrong with that.&lt;/p&gt;

&lt;p&gt;I'm talking about understanding why something was done a certain way.&lt;/p&gt;

&lt;p&gt;If all I can remember about a feature is that AI wrote it and it worked, I haven't really learned much from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sometimes the interesting part is the problem you didn't know existed
&lt;/h2&gt;

&lt;p&gt;I've been working on a text editor called &lt;a href="https://github.com/pinkpixel-dev/slate" rel="noopener noreferrer"&gt;Slate&lt;/a&gt;, which has been a really interesting learning experience for me.&lt;/p&gt;

&lt;p&gt;One thing I hadn't given much thought to before was what actually happens when you save a file while you're still editing it.&lt;/p&gt;

&lt;p&gt;I mean, saving a file sounds pretty simple, right? Write the contents to disk, mark it as saved, done.&lt;/p&gt;

&lt;p&gt;Except what happens if the user keeps typing while that save is happening?&lt;/p&gt;

&lt;p&gt;The file being written contains the older content, but the editor now has newer changes. So if the save finishes and the editor clears the unsaved indicator, it's basically telling the user everything is saved when it isn't.&lt;/p&gt;

&lt;p&gt;Slate uses revision-based save tracking to handle this. When a save starts, it remembers which revision of the document it's saving. That way, any changes made while the save is happening don't accidentally get marked as saved too.&lt;/p&gt;

&lt;p&gt;Now, AI could have just implemented all of that for me. I could have tested the save button, seen that it worked, and moved on with my life.&lt;/p&gt;

&lt;p&gt;But understanding why that revision tracking matters is what makes it useful to me.&lt;/p&gt;

&lt;p&gt;It's not really about the code itself. It's about recognizing that something can change between the time an operation starts and the time it finishes.&lt;/p&gt;

&lt;p&gt;And that's a problem that could come up in all kinds of applications, not just text editors.&lt;/p&gt;

&lt;p&gt;That's the kind of thing I want to take away from a project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actually experimenting makes a huge difference
&lt;/h2&gt;

&lt;p&gt;I've noticed the same thing when working with local AI models.&lt;/p&gt;

&lt;p&gt;Let's say I run a model and it takes 30 seconds to complete something.&lt;/p&gt;

&lt;p&gt;Okay, so it's slow. Right?&lt;/p&gt;

&lt;p&gt;Well, maybe. But what actually took 30 seconds?&lt;/p&gt;

&lt;p&gt;Was most of that time spent loading the model into memory? Was the actual processing slow? Would running it a second time be significantly faster?&lt;/p&gt;

&lt;p&gt;Those are all things I can test.&lt;/p&gt;

&lt;p&gt;And I find that I learn a lot more when I actually start experimenting instead of just asking AI to explain what's happening.&lt;/p&gt;

&lt;p&gt;Run it again. Measure things separately. Change something. See what happens.&lt;/p&gt;

&lt;p&gt;Sometimes the results are exactly what I expected. Other times they're not even close, which is usually when things get interesting.&lt;/p&gt;

&lt;p&gt;I love that I can use AI to help me figure things out. I can ask what else I should try, or why the result isn't what I expected.&lt;/p&gt;

&lt;p&gt;That makes learning unfamiliar things so much easier.&lt;/p&gt;

&lt;p&gt;But there's a big difference between AI telling me why something should happen and me actually seeing what does happen.&lt;/p&gt;

&lt;p&gt;And sometimes AI's explanation is wrong, too. Which I am sure we all know.&lt;/p&gt;

&lt;h2&gt;
  
  
  I don't necessarily remember the code, but I remember the problem
&lt;/h2&gt;

&lt;p&gt;I think this is probably the biggest thing I've noticed.&lt;/p&gt;

&lt;p&gt;When I really spend time understanding something, I might not remember the exact implementation later. But I remember the problem I was trying to solve and why I solved it that way.&lt;/p&gt;

&lt;p&gt;And that carries over into other projects.&lt;/p&gt;

&lt;p&gt;Maybe I start wondering whether some asynchronous operation could finish after the user has already changed something.&lt;/p&gt;

&lt;p&gt;Or whether a performance issue is actually a startup issue.&lt;/p&gt;

&lt;p&gt;Or whether I'm storing some piece of state that I could just calculate from something else.&lt;/p&gt;

&lt;p&gt;I might still need to look things up. I might still ask AI to help me write the implementation.&lt;/p&gt;

&lt;p&gt;But at least I know what I'm looking for and why it matters.&lt;/p&gt;

&lt;p&gt;If I just accept the generated code without thinking much about it, I miss all of that. The solution is sitting right there in my project, but I might not even recognize the same problem when I run into it somewhere else.&lt;/p&gt;

&lt;p&gt;And considering how often I start new projects, there's a pretty good chance I will run into it somewhere else. Probably next week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Of course, I don't need to turn everything into a learning experience
&lt;/h2&gt;

&lt;p&gt;I also think there's a balance here.&lt;/p&gt;

&lt;p&gt;Sometimes I just want AI to fix the padding on a button.&lt;/p&gt;

&lt;p&gt;I don't need to spend 45 minutes investigating the underlying principles of CSS spacing. I just want the button to look right.&lt;/p&gt;

&lt;p&gt;And there are plenty of things I'm perfectly happy to let AI handle. Boilerplate, repetitive changes, things I've already done a hundred times, or just tedious work I don't feel like doing.&lt;/p&gt;

&lt;p&gt;That's part of why I use these tools in the first place.&lt;/p&gt;

&lt;p&gt;But when I'm building something unfamiliar, or working on functionality that I know I'll need to maintain later, I try to be a little more involved.&lt;/p&gt;

&lt;p&gt;Sometimes that means just asking questions.&lt;/p&gt;

&lt;p&gt;Other times I might just start changing things to see what happens.&lt;/p&gt;

&lt;p&gt;I think even something as simple as predicting what a change will do before running it can make a difference. Because if the result isn't what I expected, now I have something to investigate.&lt;/p&gt;

&lt;p&gt;Do I do this every time? Absolutely not.&lt;/p&gt;

&lt;p&gt;Sometimes I've been staring at something for two hours, AI finally gets it working, and my entire thought process is basically "thank you, finally, moving on."&lt;/p&gt;

&lt;p&gt;I'm not going to pretend otherwise.&lt;/p&gt;

&lt;p&gt;But I am trying to be more conscious of when I'm actually learning something and when I'm just getting something done.&lt;/p&gt;

&lt;p&gt;Because those aren't always the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting something working isn't the same as learning how it works
&lt;/h2&gt;

&lt;p&gt;One of my favorite things about AI coding tools is how much more willing I am to try things I know very little about.&lt;/p&gt;

&lt;p&gt;I've experimented with languages, frameworks, local models, desktop applications, and all kinds of other things that I probably would have put off before.&lt;/p&gt;

&lt;p&gt;Not necessarily because I couldn't learn them, but because getting started on something completely unfamiliar can be a lot of work.&lt;/p&gt;

&lt;p&gt;AI makes that initial hurdle so much smaller, and I think that's genuinely awesome.&lt;/p&gt;

&lt;p&gt;But there's also a temptation to just keep building. One feature works, so you move on to the next one. Then the next. Before you know it, you've got a whole application and only a vague understanding of some pretty important parts of it.&lt;/p&gt;

&lt;p&gt;And it's so easy to confuse all that progress with learning.&lt;/p&gt;

&lt;p&gt;I've definitely done it.&lt;/p&gt;

&lt;p&gt;I think the things that stick with me the most are usually the things I had to investigate a little. Something didn't behave the way I expected, or I got curious about why it worked a certain way, and I spent some time figuring it out.&lt;/p&gt;

&lt;p&gt;Sometimes that investigation only takes a few minutes. Sometimes it sends me down a rabbit hole for the rest of the night.&lt;/p&gt;

&lt;p&gt;Either way, I tend to remember those experiences a lot more than the features that worked perfectly on the first try.&lt;/p&gt;

&lt;p&gt;And that's something I want to keep in mind as I continue building with AI.&lt;/p&gt;

&lt;p&gt;I don't want to stop using these tools or intentionally make everything harder for myself.&lt;/p&gt;

&lt;p&gt;I just don't want to get so caught up in how much I can build that I forget to pay attention to what I'm learning along the way.&lt;/p&gt;

&lt;p&gt;So... what about you? Have you learned something useful while building with AI that you can now troubleshoot or explain yourself? Or have you ever gone back to AI-generated code and realized you had absolutely no idea how it worked?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>learning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I Built an AI Game That Wants You to Go Outside</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Sat, 10 Oct 2026 03:58:49 +0000</pubDate>
      <link>https://dev.to/sizzlebop/i-built-an-ai-game-that-wants-you-to-go-outside-3a6k</link>
      <guid>https://dev.to/sizzlebop/i-built-an-ai-game-that-wants-you-to-go-outside-3a6k</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;I spend way too much time at my computer. Between coding, experimenting with AI models, and starting new projects when I have a perfectly good collection of unfinished ones already, I don't exactly have a shortage of reasons to stay indoors.&lt;/p&gt;

&lt;p&gt;So when I saw that the theme for this week's Hacktoberfest challenge was &lt;strong&gt;Touch Grass&lt;/strong&gt;, I immediately thought it would be fun to build an AI-powered game that encourages people to get &lt;em&gt;away&lt;/em&gt; from their computers.&lt;/p&gt;

&lt;p&gt;Which is a little ironic, considering how many hours I then spent at my computer building it. But anyway.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;Side Quest&lt;/strong&gt;!&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://side-quest.pinkpixel.dev/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;side-quest.pinkpixel.dev&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Side Quest is a little outdoor adventure game powered by Google's Gemma model. The idea is pretty simple: you tell the game a little about where you are and what it's like outside, and Gemma comes up with a small quest for you to complete in the real world.&lt;/p&gt;

&lt;p&gt;Maybe you're walking through a park on a fall afternoon. Maybe you're just hanging out in your backyard. Gemma takes your surroundings, the season, weather, and time of day into account and gives you something to go find.&lt;/p&gt;

&lt;p&gt;You head outside, find whatever it asked for, and take a picture. Then Gemma examines your photo to decide whether you've actually completed the quest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When you successfully complete a quest, you hatch a little creature inspired by whatever you found.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course I had to add a creature collection. I love games where you can discover and collect things, and I thought it would be great to have something to show for all those little outdoor adventures.&lt;/p&gt;

&lt;p&gt;Plus, I liked the idea of making people pay attention to things they might normally walk right past. An interesting looking leaf, an unusual rock, a shape in a tree. The kinds of things you might notice if you weren't staring at your phone.&lt;/p&gt;

&lt;p&gt;Yes, I realize the irony of using your phone to play a game that's supposed to get you to stop staring at your phone.&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%2Fotnhh0nm4ns6ads3oaro.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%2Fotnhh0nm4ns6ads3oaro.png" alt="Side Quest homepage with its creature specimen sheet" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The gameplay is pretty straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set the scene.&lt;/strong&gt; Tell Gemma where you are, what the weather is like, what season it is, and what time of day. You can choose from the options or describe your location yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get your quest.&lt;/strong&gt; Gemma creates a little challenge based on your surroundings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go find it!&lt;/strong&gt; Head outside, explore a bit, and take a photo of whatever you discover.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get judged by Gemma.&lt;/strong&gt; The model examines your photo to see whether it matches the challenge. If it doesn't, it'll tell you why, and you can give it another shot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hatch a creature.&lt;/strong&gt; Complete the quest and get a new little companion for your collection.&lt;/li&gt;
&lt;/ol&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%2F4w65km1xpj13o4ea6r91.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%2F4w65km1xpj13o4ea6r91.png" alt="A quest generated for the player's surroundings" width="799" height="424"&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%2F64yolk1egbrqk08es7ls.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%2F64yolk1egbrqk08es7ls.png" alt="Submitting photographic proof of a quest" width="799" height="424"&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%2Fs3iy1xk7au5fg933z6un.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%2Fs3iy1xk7au5fg933z6un.png" alt="Gemma examining a submitted photo" width="799" height="424"&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%2F5ozdvt3jtl8lbf40r2nc.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%2F5ozdvt3jtl8lbf40r2nc.png" alt="A newly hatched creature" width="799" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The creatures were especially fun to work on.&lt;/p&gt;

&lt;p&gt;I didn't want to just make ten pre-designed creatures and randomly hand one out whenever someone completed a quest. That felt a little boring.&lt;/p&gt;

&lt;p&gt;Instead, Gemma looks at the photo and describes characteristics that could inspire a creature. The app then uses those traits to draw a little SVG character.&lt;/p&gt;

&lt;p&gt;The photo also determines a consistent seed, so submitting the same image produces the same creature.&lt;/p&gt;

&lt;p&gt;It's not generating a whole new image through an API. The creatures are actually drawn by the app, using the details Gemma provides.&lt;/p&gt;

&lt;p&gt;I love this because your reward is connected to something you really found outside. And honestly, seeing what kind of little creature is going to hatch is half the fun.&lt;/p&gt;

&lt;p&gt;There's also a collection where you can look through your creatures alongside the original photos. It's basically a nature journal, except everything has adorable little faces.&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%2Fyeh8enn0scfxnt9694ro.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%2Fyeh8enn0scfxnt9694ro.png" alt="The creature collection" width="799" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also added a &lt;strong&gt;Scavenger Hunt&lt;/strong&gt; mode!&lt;/p&gt;

&lt;p&gt;Instead of getting one quest at a time, Gemma gives you a list of things to find during a walk. You can take photos of everything and submit the whole collection for judging.&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%2Fc64o8hdet5noq9dwa7l4.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%2Fc64o8hdet5noq9dwa7l4.png" alt="A multi-item scavenger hunt" width="799" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wanted Side Quest to be something that kids and adults could both enjoy. Something you could play with your family, or just by yourself when you need an excuse to get away from your desk for a while.&lt;/p&gt;

&lt;p&gt;It's not trying to be a fitness app. There are no step counts, exercise goals, or leaderboards.&lt;/p&gt;

&lt;p&gt;It's just a little game that makes going outside and exploring your surroundings more interesting.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Play Side Quest:&lt;/strong&gt; &lt;a href="https://side-quest.pinkpixel.dev" rel="noopener noreferrer"&gt;https://side-quest.pinkpixel.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can try Side Quest right in your browser.&lt;/p&gt;

&lt;p&gt;For desktop, you'll need a recent Chrome or Edge browser with WebGPU support. Click &lt;strong&gt;Wake Gemma&lt;/strong&gt;, and the model will load directly into your browser.&lt;/p&gt;

&lt;p&gt;One thing to be aware of: the initial model download is around 3.4 GB. So you'll probably want to be on Wi-Fi for that first visit. Once it's downloaded, the model is cached in your browser.&lt;/p&gt;

&lt;p&gt;The desktop version is great for trying everything out, but obviously, carrying your computer outside to photograph a leaf isn't exactly practical.&lt;/p&gt;

&lt;p&gt;That's where the mobile experience comes in.&lt;/p&gt;

&lt;p&gt;You can use your computer as a &lt;strong&gt;home base&lt;/strong&gt; that runs Gemma while you take your phone outside to complete quests.&lt;/p&gt;

&lt;p&gt;Just sign in with GitHub on your computer, leave Gemma running in the home-base tab, and scan the pairing QR code with your phone.&lt;/p&gt;

&lt;p&gt;Then you're ready to go exploring.&lt;/p&gt;

&lt;p&gt;Your phone handles the quests, photos, and creature collection while your computer does all the heavy AI work.&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%2Fin5d5wg5yri31dkzxklz.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%2Fin5d5wg5yri31dkzxklz.png" alt="The desktop home base that runs Gemma for the phone" width="799" height="424"&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%2Fbvfogv936pnawigt7ds7.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%2Fbvfogv936pnawigt7ds7.png" alt="A quest on the mobile interface" width="800" height="1731"&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%2Flq21n0dfgm0qjqncxlyc.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%2Flq21n0dfgm0qjqncxlyc.png" alt="A find sent from the phone to the home base" width="800" height="1731"&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%2Fscxxa381nsz3cxqn3v43.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%2Fscxxa381nsz3cxqn3v43.png" alt="A newly hatched creature appearing on mobile" width="800" height="1731"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also made sure the phone can hold onto your photos when you don't have a connection. They'll sit in a local queue and send when you're back online.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/pinkpixel-dev/side-quest" rel="noopener noreferrer"&gt;https://github.com/pinkpixel-dev/side-quest&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Side Quest is open source under the Apache 2.0 license.&lt;/p&gt;

&lt;p&gt;The repo includes the React frontend, Gemma inference worker, quest generation and creature logic, Cloudflare Worker backend, optional private home-base server, and tests.&lt;/p&gt;

&lt;p&gt;If you'd like to run the basic solo version locally, it's pretty simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open &lt;code&gt;http://localhost:5173&lt;/code&gt; in a desktop browser that supports WebGPU.&lt;/p&gt;

&lt;p&gt;The README has more detailed instructions for setting up the hosted features, account authentication, and the private phone-to-desktop option.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Putting Gemma to work
&lt;/h3&gt;

&lt;p&gt;For the AI side of things, I used Gemma 4 E2B, Google's open-weight multimodal model, running with Transformers.js and WebGPU.&lt;/p&gt;

&lt;p&gt;I'm using the 4-bit ONNX version, &lt;code&gt;onnx-community/gemma-4-E2B-it-ONNX&lt;/code&gt;, which loads in a web worker so the model isn't blocking the main UI.&lt;/p&gt;

&lt;p&gt;I've been having a lot of fun experimenting with models running directly in the browser lately, so I was excited to have an excuse to build something a little different with one.&lt;/p&gt;

&lt;p&gt;And Gemma isn't just there to generate some flavor text. It's actually responsible for the main parts of the game.&lt;/p&gt;

&lt;p&gt;It handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quest generation:&lt;/strong&gt; Creating challenges based on your surroundings, weather, season, and time of day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Photo judging:&lt;/strong&gt; Looking at your submitted image and deciding whether you actually found what the quest asked for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creature traits:&lt;/strong&gt; Describing features inspired by your photo that the app can use to draw your new creature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scavenger hunts:&lt;/strong&gt; Coming up with multiple things to find and evaluating the collected photos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I especially like that Gemma evaluates your photo and describes the creature together. Your discovery actually influences what you get as a reward.&lt;/p&gt;

&lt;p&gt;For the rest of the stack, I used React 19, TypeScript, Vite 8, and Tailwind CSS 4.&lt;/p&gt;

&lt;p&gt;IndexedDB handles the local storage for quests, photos, completed finds, and creatures. And the creatures themselves are generated as SVGs, so there's no need for a separate image generation model or service.&lt;/p&gt;

&lt;h3&gt;
  
  
  The part that got complicated
&lt;/h3&gt;

&lt;p&gt;There was one pretty obvious problem with my whole idea.&lt;/p&gt;

&lt;p&gt;I wanted people to use this game while walking around outside. But the Gemma model runs best with a desktop GPU.&lt;/p&gt;

&lt;p&gt;Not exactly ideal for a mobile game.&lt;/p&gt;

&lt;p&gt;Naturally, I decided to see if I could get it running on my iPhone 12 anyway.&lt;/p&gt;

&lt;p&gt;That experiment ended pretty quickly.&lt;/p&gt;

&lt;p&gt;The browser made it about 500 MB into downloading the 3.4 GB model before deciding it had had enough and killing the tab.&lt;/p&gt;

&lt;p&gt;So, there goes that idea.&lt;/p&gt;

&lt;p&gt;I could have switched to a cloud AI API and called it a day. But I really wanted to keep Gemma running locally, and I wasn't ready to give up on that part.&lt;/p&gt;

&lt;p&gt;So I came up with a different approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let the phone do the exploring and let the computer do the thinking.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The desktop browser loads Gemma and acts as a home base. Your phone connects to it and becomes the lightweight interface you actually carry around.&lt;/p&gt;

&lt;p&gt;When you submit a photo, it gets sent back to your home base, where Gemma evaluates it and generates the creature traits. The result then comes back to your phone.&lt;/p&gt;

&lt;p&gt;The model never has to run on the phone, and there's no cloud AI inference service involved.&lt;/p&gt;

&lt;p&gt;I also added some quest pre-generation. The home base prepares a little pool of quests and scavenger hunts ahead of time, so you don't have to stand around waiting for Gemma to think of something every time you want a new one.&lt;/p&gt;

&lt;p&gt;If you change your surroundings or conditions, the old quests get discarded and new ones are generated.&lt;/p&gt;

&lt;p&gt;And because I wanted the game to work when someone loses their signal, the mobile app saves unsent finds in IndexedDB and retries them once the connection returns.&lt;/p&gt;

&lt;p&gt;What started as a simple little outdoor game was suddenly turning into a whole phone-to-desktop AI system.&lt;/p&gt;

&lt;p&gt;You know how these things go. One little feature leads to another, and before you know it, you've built three extra systems just to make the original idea work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making the setup less ridiculous
&lt;/h3&gt;

&lt;p&gt;My original solution used a local Node server and a temporary Cloudflare tunnel to connect the phone to the desktop.&lt;/p&gt;

&lt;p&gt;It worked, and I actually kept that option in the project. You can still run it with &lt;code&gt;npm run home&lt;/code&gt; if you prefer a private, self-hosted setup.&lt;/p&gt;

&lt;p&gt;But then I started thinking about what it would be like for someone who just wanted to try the game.&lt;/p&gt;

&lt;p&gt;Imagine telling someone:&lt;/p&gt;

&lt;p&gt;"Hey, I made this cute little game where you go outside and find things. First, install Node, download some dependencies, run a server, start a tunnel, and pair your phone."&lt;/p&gt;

&lt;p&gt;Yeah. No.&lt;/p&gt;

&lt;p&gt;That's a lot of work just to go look for an interesting rock.&lt;/p&gt;

&lt;p&gt;So I added a hosted option to make the whole process easier.&lt;/p&gt;

&lt;p&gt;It uses a &lt;strong&gt;Cloudflare Worker&lt;/strong&gt; to relay messages between your phone and the home-base browser, &lt;strong&gt;D1&lt;/strong&gt; for account and quest data, and &lt;strong&gt;R2&lt;/strong&gt; for photo storage.&lt;/p&gt;

&lt;p&gt;You sign in with GitHub on your desktop, scan a temporary QR code with your phone, and you're connected.&lt;/p&gt;

&lt;p&gt;Your creature collection can also sync between your signed-in devices.&lt;/p&gt;

&lt;p&gt;The important part is that &lt;strong&gt;Cloudflare isn't running the AI model&lt;/strong&gt;. Gemma still runs locally in your desktop browser using your GPU. The hosted services just handle communication and storage.&lt;/p&gt;

&lt;p&gt;I also wanted to be clear about what happens to your data, because I think that's important when talking about local AI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solo mode:&lt;/strong&gt; Your photos and game data stay in your browser's local storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosted mode:&lt;/strong&gt; Photos go through the Cloudflare Worker and are stored in R2. You can delete your account, including its associated photos and records.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private home-base mode:&lt;/strong&gt; Your photos stay on your own computer instead of being stored in the hosted service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location:&lt;/strong&gt; The game doesn't track your GPS coordinates. If you enter a location, it's just text used to help Gemma create an appropriate quest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So while the AI inference is local, I'm not going to pretend that every part of the hosted experience is completely offline.&lt;/p&gt;

&lt;h3&gt;
  
  
  A few things I learned along the way
&lt;/h3&gt;

&lt;p&gt;One thing that surprised me about this project was how little of the actual work involved getting Gemma to generate text.&lt;/p&gt;

&lt;p&gt;That part was fun, of course. But once I got into the phone-to-desktop setup, I found myself spending a lot more time dealing with state synchronization, queued requests, connection handling, and making sure everything still behaved properly when one device went offline.&lt;/p&gt;

&lt;p&gt;Basically, all the less exciting stuff that has to work before you can enjoy the exciting stuff.&lt;/p&gt;

&lt;p&gt;I also ran into a particularly annoying issue with Cloudflare Worker requests.&lt;/p&gt;

&lt;p&gt;My tests were passing, but when I tried making requests through the actual Vite development proxy, I kept getting &lt;strong&gt;403 errors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It turned out that the test harness and development proxy were presenting different combinations of request URLs and &lt;code&gt;Origin&lt;/code&gt; headers. My origin validation was fine in the tests, but it was rejecting legitimate requests in the browser.&lt;/p&gt;

&lt;p&gt;The fix was to account for the request host or explicitly configured application origin, and to make sure I was testing through the actual development proxy rather than relying entirely on the test harness.&lt;/p&gt;

&lt;p&gt;A good reminder that passing tests don't necessarily mean everything works in the real world.&lt;/p&gt;

&lt;p&gt;I used &lt;strong&gt;Vitest&lt;/strong&gt; for testing, including Wrangler's test harness with local D1 and R2 bindings for the Cloudflare Worker.&lt;/p&gt;

&lt;p&gt;Not quite as exciting as hatching adorable little creatures, but I suppose the plumbing has to work too.&lt;/p&gt;

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

&lt;p&gt;This is actually one of my favorite things about building projects with open-weight models.&lt;/p&gt;

&lt;p&gt;I love experimenting with AI, especially when I can run models locally and figure out interesting ways to use them.&lt;/p&gt;

&lt;p&gt;And I think projects like Side Quest are a great example of why having access to those models matters.&lt;/p&gt;

&lt;p&gt;Sure, I could have built this game using a hosted vision API. It probably would have been easier in some ways.&lt;/p&gt;

&lt;p&gt;But then every quest, every photo evaluation, and every creature would mean another request to an external AI service.&lt;/p&gt;

&lt;p&gt;With Gemma, I can run the model directly on my own hardware, experiment with how it behaves, and build an entire little game around it without paying for every interaction.&lt;/p&gt;

&lt;p&gt;For the core solo experience, there's no account required, no external AI API, and no server processing your photos. The model runs right in your browser.&lt;/p&gt;

&lt;p&gt;And because the model is available to run myself, I can actually experiment with it.&lt;/p&gt;

&lt;p&gt;I can change the prompts, adjust the structured outputs, fine-tune how quests are judged, and try different approaches to generating creature traits. I could even experiment with other compatible models in the future.&lt;/p&gt;

&lt;p&gt;I'm not limited to whatever features a hosted API happens to expose.&lt;/p&gt;

&lt;p&gt;But I think the most interesting part of this project is how that freedom influenced the design.&lt;/p&gt;

&lt;p&gt;When I realized Gemma wasn't going to run on my phone, I didn't have to abandon local inference entirely.&lt;/p&gt;

&lt;p&gt;Instead, I found a way to use my desktop browser as a tiny personal AI server while my phone handles the actual gameplay.&lt;/p&gt;

&lt;p&gt;And I think that's pretty awesome.&lt;/p&gt;

&lt;p&gt;It also makes me wonder what else you could build using that same approach. A powerful local model running on one device, with lightweight interfaces connecting to it from somewhere else. There's a lot of room to experiment there.&lt;/p&gt;

&lt;p&gt;Of course, local AI isn't without its limitations. The model download is pretty hefty, you need hardware that can run it, and the optional hosted features still involve cloud services.&lt;/p&gt;

&lt;p&gt;But open-weight models give developers more choices about how to build things, and I love that.&lt;/p&gt;

&lt;p&gt;Not everything needs to be another app that sends a prompt to a paid API and displays the response.&lt;/p&gt;

&lt;p&gt;Sometimes you can get a little more creative with it.&lt;/p&gt;

&lt;p&gt;And in this case, I used an AI model to build a game that encourages people to spend &lt;em&gt;less&lt;/em&gt; time interacting with AI.&lt;/p&gt;

&lt;p&gt;I still find that pretty funny.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma 4 E2B powers the core gameplay, including context-aware quest generation, multimodal photo judging, scavenger hunts, and creature trait generation. It runs locally in the browser using Transformers.js and WebGPU.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I had a lot of fun building this one!&lt;/p&gt;

&lt;p&gt;It turned out to be a bit more involved than I originally expected, especially once I decided that the game really needed to work on a phone. But figuring out how to make that happen while keeping Gemma running locally was probably the most interesting part of the whole project.&lt;/p&gt;

&lt;p&gt;And I genuinely love the little creatures. I could probably spend a lot of time just seeing what kinds of things Gemma comes up with from different photos.&lt;/p&gt;

&lt;p&gt;I also think it's nice to build something that's just meant to be fun.&lt;/p&gt;

&lt;p&gt;Not every AI project needs to automate your entire life, make you more productive, or solve some enormous problem.&lt;/p&gt;

&lt;p&gt;Sometimes it's perfectly fine to build something that just gets people to go outside and take pictures of leaves.&lt;/p&gt;

&lt;p&gt;If you give Side Quest a try, I'd love to hear what you think! And especially what kind of creatures you end up hatching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://side-quest.pinkpixel.dev" rel="noopener noreferrer"&gt;Play Side Quest&lt;/a&gt;&lt;/strong&gt; | &lt;strong&gt;&lt;a href="https://github.com/pinkpixel-dev/side-quest" rel="noopener noreferrer"&gt;Check out the source on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>showdev</category>
      <category>gemma</category>
    </item>
    <item>
      <title>Learning GPUI by Building My Own Text Editor</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Thu, 08 Oct 2026 21:30:39 +0000</pubDate>
      <link>https://dev.to/sizzlebop/learning-gpui-by-building-my-own-text-editor-2pmb</link>
      <guid>https://dev.to/sizzlebop/learning-gpui-by-building-my-own-text-editor-2pmb</guid>
      <description>&lt;p&gt;I've been wanting to experiment with &lt;a href="https://www.gpui.rs/" rel="noopener noreferrer"&gt;GPUI&lt;/a&gt; for a while now. It's the Rust UI framework developed for Zed, and I was curious what it would be like to use it for something of my own.&lt;/p&gt;

&lt;p&gt;So, naturally, I decided to build a text editor.&lt;/p&gt;

&lt;p&gt;Because apparently the best way to learn a new UI framework is to pick a project that already has about a million little details to get right.&lt;/p&gt;

&lt;p&gt;Anyway, the result is &lt;strong&gt;Slate&lt;/strong&gt;, a lightweight, native text editor for Linux, built with Rust and &lt;a href="https://gpui-kit.com/" rel="noopener noreferrer"&gt;GPUI Kit&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%2Frf4xzh9ihdcf29j85eqb.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%2Frf4xzh9ihdcf29j85eqb.png" alt="Slate text editor" width="799" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why GPUI?
&lt;/h2&gt;

&lt;p&gt;Most of the desktop apps I've worked on have used web technologies, so I wanted to try something different.&lt;/p&gt;

&lt;p&gt;GPUI caught my attention because it's the framework behind &lt;a href="https://zed.dev/" rel="noopener noreferrer"&gt;Zed&lt;/a&gt;, and I really like the idea of building native desktop interfaces with Rust.&lt;/p&gt;

&lt;p&gt;Rather than having a web frontend wrapped in a desktop shell, GPUI lets you build the interface directly in Rust.&lt;/p&gt;

&lt;p&gt;Of course, that also means learning a different way of thinking about UI development.&lt;/p&gt;

&lt;p&gt;I was especially interested in seeing how practical it would be to build a complete application with it, rather than just experimenting with a few buttons and windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovering GPUI Kit
&lt;/h2&gt;

&lt;p&gt;One thing I quickly realized is that GPUI itself isn't a complete collection of ready-made application components.&lt;/p&gt;

&lt;p&gt;And writing an entire text editing component from scratch wasn't exactly what I had in mind.&lt;/p&gt;

&lt;p&gt;Thankfully, I found &lt;a href="https://github.com/longbridge/gpui-kit" rel="noopener noreferrer"&gt;GPUI Kit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GPUI Kit provides a collection of components built on GPUI, including things like tabs, dialogs, menus, trees, themes, and most importantly for this project, an actual text editor component.&lt;/p&gt;

&lt;p&gt;That last part made a huge difference.&lt;/p&gt;

&lt;p&gt;Building a text editor involves a lot more than displaying text and responding to keyboard input. You need to deal with cursor movement, selections, undo history, syntax highlighting, multiple cursors, and all kinds of behavior that people expect to just work.&lt;/p&gt;

&lt;p&gt;GPUI Kit already handles much of that.&lt;/p&gt;

&lt;p&gt;It gave me a foundation to build on so I could focus on making the application I wanted rather than spending forever implementing basic editing functionality.&lt;/p&gt;

&lt;p&gt;That doesn't mean everything was plug-and-play, though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Slate
&lt;/h2&gt;

&lt;p&gt;I wanted Slate to fit somewhere between a very basic text editor and a full-featured editor like Kate.&lt;/p&gt;

&lt;p&gt;Something I could open quickly to edit a config file, work on some Markdown, or browse a few source files without launching an entire IDE.&lt;/p&gt;

&lt;p&gt;I also wanted it to look nice. That's important to me, even with small utility apps.&lt;/p&gt;

&lt;p&gt;One of the things I particularly wanted was color-coded tabs. When I have a bunch of files open, I like being able to distinguish them at a glance.&lt;/p&gt;

&lt;p&gt;GPUI Kit has a tab component, but it didn't support the drag-and-drop reordering or colored accent lines I wanted.&lt;/p&gt;

&lt;p&gt;So I built Slate's tab strip myself using GPUI, while still using Kit's components for things like context menus and tooltips.&lt;/p&gt;

&lt;p&gt;That ended up being a pretty good example of how I approached the project: use GPUI Kit wherever it made sense, then build the parts that needed something different.&lt;/p&gt;

&lt;p&gt;The same thing happened with the find and replace bar. GPUI Kit already has the underlying search functionality, but I wanted the interface to sit neatly above the editor instead of floating over it.&lt;/p&gt;

&lt;p&gt;So I reused Kit's search engine and built my own interface around it.&lt;/p&gt;

&lt;p&gt;I actually enjoyed that flexibility quite a bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some things I learned along the way
&lt;/h2&gt;

&lt;p&gt;Working with GPUI and GPUI Kit was interesting, but there were definitely some challenges.&lt;/p&gt;

&lt;p&gt;One of the biggest lessons was learning to work within the public APIs that the component library exposes.&lt;/p&gt;

&lt;p&gt;For example, GPUI Kit supports multiple cursors, but the version I'm using doesn't expose a public method for programmatically adding a selection at a specific range.&lt;/p&gt;

&lt;p&gt;That meant a feature I wanted, &lt;code&gt;Ctrl+D&lt;/code&gt; to select the next occurrence of some text, wasn't something I could easily implement without modifying the library.&lt;/p&gt;

&lt;p&gt;It's on hold for now.&lt;/p&gt;

&lt;p&gt;Another interesting challenge was the minimap.&lt;/p&gt;

&lt;p&gt;I wanted a little overview of the file along the right side, similar to what you see in VS Code.&lt;/p&gt;

&lt;p&gt;The problem was that GPUI Kit's editor doesn't expose all the layout and syntax information needed to draw one directly.&lt;/p&gt;

&lt;p&gt;I ended up creating a custom minimap using GPUI's canvas rendering, with a separate syntax highlighter providing the colors.&lt;/p&gt;

&lt;p&gt;There's also a catch with wrapped lines. Without access to the editor's exact line layout, the minimap's viewport indicator wouldn't always line up correctly.&lt;/p&gt;

&lt;p&gt;Rather than leave something that behaved incorrectly, I decided to hide the minimap when word wrap is enabled.&lt;/p&gt;

&lt;p&gt;Not the most exciting compromise, but it works reliably.&lt;/p&gt;

&lt;p&gt;I ran into some other interesting issues with theme reloading, file watching, keyboard events, and Linux window behavior.&lt;/p&gt;

&lt;p&gt;These are exactly the kinds of details that are easy to overlook until you're building an application that needs to handle them.&lt;/p&gt;

&lt;p&gt;And honestly, working through those problems was a big part of why I wanted to try this project in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Slate can do now
&lt;/h2&gt;

&lt;p&gt;Even though I started Slate as a way to learn GPUI, it ended up becoming a pretty capable little editor.&lt;/p&gt;

&lt;p&gt;Some of the features in the first release include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Syntax highlighting for 23 languages&lt;/strong&gt;, powered by Tree-sitter through GPUI Kit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple tabs&lt;/strong&gt;, including drag-and-drop reordering and customizable tab colors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;39 built-in themes&lt;/strong&gt;, including Catppuccin, Gruvbox, Tokyo Night, and several Slate-specific themes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File sidebar&lt;/strong&gt; with automatic updates, folder navigation, and hidden-file controls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find and replace&lt;/strong&gt;, Quick Open, and a searchable command palette&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session restore&lt;/strong&gt;, including unsaved edits, so you can pick up where you left off&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Markdown preview&lt;/strong&gt; in a split view&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Syntax-colored minimap&lt;/strong&gt; for navigating longer files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clickable color swatches&lt;/strong&gt; for editing hex, RGB, and HSL colors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File change detection&lt;/strong&gt;, including the ability to compare your edits against the version on disk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are plenty of smaller conveniences too, like line duplication, moving lines up and down, comment toggling, indentation detection, and opening files directly from the terminal.&lt;/p&gt;

&lt;p&gt;I also made the themes customizable. You can drop a JSON theme file into Slate's themes folder and edit it while the app is running. Slate watches for changes and updates the appearance automatically.&lt;/p&gt;

&lt;p&gt;That was a particularly fun feature to get working.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first release is available
&lt;/h2&gt;

&lt;p&gt;Slate 1.0 is now available on &lt;a href="https://github.com/pinkpixel-dev/slate" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's currently Linux-only, and I've been developing and testing it on CachyOS with the COSMIC desktop.&lt;/p&gt;

&lt;p&gt;If you're using Arch or an Arch-based distribution, you can install it from the AUR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yay &lt;span class="nt"&gt;-S&lt;/span&gt; slate-editor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if you'd rather build it yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/pinkpixel-dev/slate.git
&lt;span class="nb"&gt;cd &lt;/span&gt;slate
cargo run &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll need Rust 1.92 or newer and a working Vulkan driver. I've included more detailed requirements and instructions in the README.&lt;/p&gt;

&lt;p&gt;And since this is the first release, I definitely wouldn't claim it's perfect. I've only tested it on my own desktop environment so far, and I'm sure there are things that will need adjusting as it gets used on other systems.&lt;/p&gt;

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

&lt;p&gt;I'm happy with how the first version turned out, but I don't consider Slate finished.&lt;/p&gt;

&lt;p&gt;There are still features and improvements I'd like to explore, especially as GPUI Kit continues developing and potentially exposes more of its editor functionality.&lt;/p&gt;

&lt;p&gt;At the same time, I don't want Slate to turn into another full IDE.&lt;/p&gt;

&lt;p&gt;There are already plenty of excellent editors that do that.&lt;/p&gt;

&lt;p&gt;My goal is to keep it lightweight, useful, and pleasant to work with. Something that does the everyday editing stuff really well without needing a hundred additional features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Building Slate gave me a much better understanding of GPUI and what it's like to develop a native desktop application with Rust.&lt;/p&gt;

&lt;p&gt;I also came away with a lot of appreciation for how much work goes into something as seemingly simple as a text editor.&lt;/p&gt;

&lt;p&gt;It's one of those applications where the interface might look straightforward, but there's an incredible amount happening underneath.&lt;/p&gt;

&lt;p&gt;GPUI Kit made this project much more approachable, and having the option to mix its existing components with custom GPUI interfaces was probably my favorite part of working with it.&lt;/p&gt;

&lt;p&gt;I'm definitely interested in experimenting with GPUI some more.&lt;/p&gt;

&lt;p&gt;If you're curious about the project, the source code is available here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/pinkpixel-dev/slate" rel="noopener noreferrer"&gt;Slate on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And if you've worked with GPUI or GPUI Kit yourself, I'd love to hear what your experience has been like!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>opensource</category>
      <category>linux</category>
      <category>showdev</category>
    </item>
    <item>
      <title>AI Is Making It Too Easy to Avoid Thinking</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Mon, 05 Oct 2026 21:55:27 +0000</pubDate>
      <link>https://dev.to/sizzlebop/ai-is-making-it-too-easy-to-avoid-thinking-3hnk</link>
      <guid>https://dev.to/sizzlebop/ai-is-making-it-too-easy-to-avoid-thinking-3hnk</guid>
      <description>&lt;p&gt;I use AI every day.&lt;/p&gt;

&lt;p&gt;I build things with it, experiment with it, write code with it, learn about new things with it, and generally think it's one of the most interesting technologies I've ever had access to.&lt;/p&gt;

&lt;p&gt;So this is definitely not an "AI is ruining everything" post.&lt;/p&gt;

&lt;p&gt;But I do think AI is creating a problem that we probably need to talk about more:&lt;/p&gt;

&lt;p&gt;It has become incredibly easy to avoid thinking.&lt;/p&gt;

&lt;p&gt;And that cannot be good for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  We used to have to struggle a little
&lt;/h2&gt;

&lt;p&gt;Say you have to write an essay about something you don't care about and are not at all interested in.&lt;/p&gt;

&lt;p&gt;Maybe it's for school. Maybe it's for work. Whatever it's for, somebody wants you to write 1,500 words about a topic you know absolutely nothing about.&lt;/p&gt;

&lt;p&gt;20 years ago that kinda sucked.&lt;/p&gt;

&lt;p&gt;You had to research it.&lt;/p&gt;

&lt;p&gt;You had to figure out what people were talking about.&lt;/p&gt;

&lt;p&gt;Read the same pages over and over again til they stuck with you.&lt;/p&gt;

&lt;p&gt;Take notes.&lt;/p&gt;

&lt;p&gt;Then you had to decide which information was important.&lt;/p&gt;

&lt;p&gt;You had to organize your thoughts.&lt;/p&gt;

&lt;p&gt;You had to stare at a blank page for twenty minutes because you had no idea where to start.&lt;/p&gt;

&lt;p&gt;You'd write something, hate it, rewrite it, realize you misunderstood something, go look it up again, take a break, come back to it, and eventually, little by little you would piece together something decent.&lt;/p&gt;

&lt;p&gt;But you had to think, and you had to do the hard thing because no one was going to do it for you.&lt;/p&gt;

&lt;p&gt;And somewhere in all of that annoyance, you probably learned something.&lt;/p&gt;

&lt;p&gt;Not just about the subject.&lt;/p&gt;

&lt;p&gt;You practiced researching.&lt;/p&gt;

&lt;p&gt;You practiced deciding whether a source made sense.&lt;/p&gt;

&lt;p&gt;You practiced turning information into your own understanding.&lt;/p&gt;

&lt;p&gt;You practiced explaining something.&lt;/p&gt;

&lt;p&gt;You practiced writing.&lt;/p&gt;

&lt;p&gt;You practiced being stuck.&lt;/p&gt;

&lt;p&gt;That last one might be the most important.&lt;/p&gt;

&lt;p&gt;And honestly you probably were feeling pretty good at the end of it all because you felt like you had accomplished something.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now the hard part is optional
&lt;/h2&gt;

&lt;p&gt;These days all you need to do is type:&lt;/p&gt;

&lt;p&gt;Write me a 1,500-word essay about this topic.&lt;/p&gt;

&lt;p&gt;And thirty seconds later, there it is.&lt;/p&gt;

&lt;p&gt;Maybe you edit it.&lt;/p&gt;

&lt;p&gt;Maybe you fix a few sentences.&lt;/p&gt;

&lt;p&gt;Maybe you read through it closely enough to make sure it doesn't say anything stupid.&lt;/p&gt;

&lt;p&gt;But you didn't actually have to do most of the work that used to happen between receiving the assignment and having the finished result.&lt;/p&gt;

&lt;p&gt;AI did the research.&lt;/p&gt;

&lt;p&gt;AI organized the ideas.&lt;/p&gt;

&lt;p&gt;AI figured out the structure.&lt;/p&gt;

&lt;p&gt;AI found the words.&lt;/p&gt;

&lt;p&gt;The end product might be perfectly fine.&lt;/p&gt;

&lt;p&gt;But producing the end product was never the only point.&lt;/p&gt;

&lt;p&gt;Sometimes the process was teaching you something too.&lt;/p&gt;

&lt;h2&gt;
  
  
  I see this with kids
&lt;/h2&gt;

&lt;p&gt;This part really worries me.&lt;/p&gt;

&lt;p&gt;If a kid has 10 math problems for homework and doesn't understand number 7, there are two very different ways to use AI.&lt;/p&gt;

&lt;p&gt;One is:&lt;/p&gt;

&lt;p&gt;What's the answer to number 7?&lt;/p&gt;

&lt;p&gt;The other is:&lt;/p&gt;

&lt;p&gt;Can you help me understand how to solve this without giving me the answer?&lt;/p&gt;

&lt;p&gt;Those might look like tiny differences in prompting.&lt;/p&gt;

&lt;p&gt;They're not.&lt;/p&gt;

&lt;p&gt;One replaces the thinking.&lt;/p&gt;

&lt;p&gt;The other supports it.&lt;/p&gt;

&lt;p&gt;And when the easiest option is always sitting three seconds away, I think it takes a surprising amount of discipline to choose the harder one.&lt;/p&gt;

&lt;p&gt;Adults definitely do it too.&lt;/p&gt;

&lt;p&gt;Why spend an hour figuring something out when you can ask an AI?&lt;/p&gt;

&lt;p&gt;Why read the documentation?&lt;/p&gt;

&lt;p&gt;Why wrestle with the bug?&lt;/p&gt;

&lt;p&gt;Why write the first draft?&lt;/p&gt;

&lt;p&gt;Why sit there thinking about how you actually feel about something?&lt;/p&gt;

&lt;p&gt;Why learn the formula when something else can calculate it for you forever?&lt;/p&gt;

&lt;p&gt;Sometimes the correct answer genuinely is: don't waste your time doing this manually.&lt;/p&gt;

&lt;p&gt;I automate things specifically because I don't want to do repetitive crap manually.&lt;/p&gt;

&lt;p&gt;But not all difficulty is useless friction.&lt;/p&gt;

&lt;p&gt;Sometimes difficulty is the exercise.&lt;/p&gt;

&lt;h2&gt;
  
  
  I think we've started confusing "hard" with "unnecessary"
&lt;/h2&gt;

&lt;p&gt;This is probably the part I think about the most.&lt;/p&gt;

&lt;p&gt;We've spent decades making technology remove friction from our lives.&lt;/p&gt;

&lt;p&gt;Usually that's awesome.&lt;/p&gt;

&lt;p&gt;I don't particularly miss having to drive to the library to do research.&lt;/p&gt;

&lt;p&gt;I don't think programmers need to give up autocomplete and start writing machine code to prove we're still using our brains.&lt;/p&gt;

&lt;p&gt;There is no virtue in making something difficult solely for the purpose of making it difficult.&lt;/p&gt;

&lt;p&gt;But I think we've started treating any mental friction as a problem technology should solve for us, and we're starting to lose the desire to accomplish something on our own.&lt;/p&gt;

&lt;p&gt;Struggling to understand something is uncomfortable.&lt;/p&gt;

&lt;p&gt;Sitting with a problem is uncomfortable.&lt;/p&gt;

&lt;p&gt;Being confused is uncomfortable.&lt;/p&gt;

&lt;p&gt;Writing badly before you learn to write well is uncomfortable.&lt;/p&gt;

&lt;p&gt;Trying 3 solutions that don't work is uncomfortable.&lt;/p&gt;

&lt;p&gt;Honestly, just being wrong is uncomfortable.&lt;/p&gt;

&lt;p&gt;But those experiences also build something.&lt;/p&gt;

&lt;p&gt;They build judgment.&lt;/p&gt;

&lt;p&gt;They build persistence.&lt;/p&gt;

&lt;p&gt;They build the ability to look at something unfamiliar and think:&lt;/p&gt;

&lt;p&gt;I have no idea how to do this, but I can probably figure it out.&lt;/p&gt;

&lt;p&gt;I'd really hate for us to lose that completely.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI can either make us better or much worse
&lt;/h2&gt;

&lt;p&gt;The weird thing is that AI might be one of the greatest learning tools we've ever invented.&lt;/p&gt;

&lt;p&gt;You can ask it to explain something to you 5 different ways until you get it.&lt;/p&gt;

&lt;p&gt;You can ask it to test you.&lt;/p&gt;

&lt;p&gt;You can argue with it.&lt;/p&gt;

&lt;p&gt;You can tell it your answer and ask what mistakes you made.&lt;/p&gt;

&lt;p&gt;You can ask it for hints instead of the answer itself.&lt;/p&gt;

&lt;p&gt;Learning can be incredibly fast with these tools.&lt;/p&gt;

&lt;p&gt;That's the part of AI I love.&lt;/p&gt;

&lt;p&gt;But the same tool can also let you skip the entire learning process.&lt;/p&gt;

&lt;p&gt;And the difference isn't really the technology.&lt;/p&gt;

&lt;p&gt;It's how we decide to use it.&lt;/p&gt;

&lt;p&gt;Sometimes I'll ask AI something and realize afterward that I probably should have spent another ten minutes thinking about it myself first.&lt;/p&gt;

&lt;p&gt;Not because using AI was cheating.&lt;/p&gt;

&lt;p&gt;Not because the machine somehow contaminated the answer.&lt;/p&gt;

&lt;p&gt;Just because I needed the exercise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maybe we need to protect some of the struggle
&lt;/h2&gt;

&lt;p&gt;I'm definitely not suggesting we stop using AI.&lt;/p&gt;

&lt;p&gt;Good luck prying it out of my hands.&lt;/p&gt;

&lt;p&gt;I think maybe we have to be more deliberate about choosing what aspects of our thought process we're comfortable delegating.&lt;/p&gt;

&lt;p&gt;Let the AI help you understand the chapter, but maybe don't let it read the chapter for you every time.&lt;/p&gt;

&lt;p&gt;Let the AI point out why your math solution is wrong, but maybe try to work out the problem yourself first.&lt;/p&gt;

&lt;p&gt;Let the AI help with debugging your code, but maybe take some time to try to understand the bug a little bit before throwing it at an AI chatbot.&lt;/p&gt;

&lt;p&gt;Let the AI critique your argument, but maybe &lt;strong&gt;figure out what you think before asking it what you should think.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because if we outsource every difficult thing the instant it becomes uncomfortable, eventually we're going to become very good at operating AI tools and very bad at operating without them.&lt;/p&gt;

&lt;p&gt;AI should give us more ability to think.&lt;/p&gt;

&lt;p&gt;It shouldn't give us an excuse not to.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>learning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I Gave My AI Agents Their Own Documentation Crawler, and Pulled 60 Pages of Clean Markdown in 49 Seconds</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Mon, 05 Oct 2026 07:40:48 +0000</pubDate>
      <link>https://dev.to/sizzlebop/i-gave-my-ai-agents-their-own-documentation-crawler-and-pulled-60-pages-of-clean-markdown-in-49-2cl7</link>
      <guid>https://dev.to/sizzlebop/i-gave-my-ai-agents-their-own-documentation-crawler-and-pulled-60-pages-of-clean-markdown-in-49-2cl7</guid>
      <description>&lt;p&gt;It's not just that I made a crawler, but it's how the docs actually look that makes me love this so much.&lt;/p&gt;

&lt;p&gt;I made an MCP server this weekend, and I am kind of in awe of how well this thing works.&lt;/p&gt;

&lt;p&gt;It's called &lt;strong&gt;pulpie-mcp&lt;/strong&gt;, and the basic idea is pretty simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Give AI coding agents their own tool for pulling full web pages and documentation into clean Markdown.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not summarized documentation. Not chopped-up search results. Not "here are the important parts I think you need."&lt;/p&gt;

&lt;p&gt;The actual content.&lt;/p&gt;

&lt;p&gt;Tables, links, images, code, headings, all turned into Markdown and saved somewhere the agent can use again later.&lt;/p&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/pinkpixel-dev" rel="noopener noreferrer"&gt;
        pinkpixel-dev
      &lt;/a&gt; / &lt;a href="https://github.com/pinkpixel-dev/pulpie-mcp" rel="noopener noreferrer"&gt;
        pulpie-mcp
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &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;pulpie-mcp&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/pinkpixel-dev/pulpie-mcp/pulpie.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fpulpie-mcp%2FHEAD%2Fpulpie.png" alt="pulpie-mcp"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An MCP server that gives AI agents their own tools for turning web pages into clean Markdown. It runs the &lt;a href="https://github.com/feyninc/pulpie" rel="noopener noreferrer"&gt;Pulpie&lt;/a&gt; content extraction model locally, so tables, code blocks, links, and images come through intact instead of getting summarized away.&lt;/p&gt;
&lt;p&gt;The agent can read a page inline, save it as a &lt;code&gt;.md&lt;/code&gt; file, crawl a whole docs section into a folder, and check what it already saved before fetching again.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why I made it&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;I already had a little local UI for Pulpie that I used to pull docs and articles into Markdown, and it works really well. But I was still the one doing the pulling. Most agent fetch tools run pages through a small model that summarizes or trims them, which is not what you want when the agent needs the actual API reference.&lt;/p&gt;
&lt;p&gt;So this gives the agent the same thing I was using. It can…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/pinkpixel-dev/pulpie-mcp" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The test that kind of blew my mind
&lt;/h2&gt;

&lt;p&gt;I had Claude test &lt;code&gt;crawl_docs&lt;/code&gt; against a documentation site with &lt;strong&gt;60 pages&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The backend wasn't already running, so this included starting the server and loading the extraction model onto my GPU.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Backend cold start&lt;/td&gt;
&lt;td&gt;~10s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crawling and saving 60 pages&lt;/td&gt;
&lt;td&gt;~37s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~49s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So in under a minute, Claude went from having none of those docs locally to having &lt;strong&gt;60 clean Markdown files&lt;/strong&gt; it could search, read, and reference.&lt;/p&gt;

&lt;p&gt;I just thought this was so awesome.&lt;/p&gt;

&lt;p&gt;And once the model is already loaded, obviously that initial ~10-second startup cost disappears.&lt;/p&gt;

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

&lt;p&gt;I've already been using &lt;a href="https://github.com/feyninc/pulpie" rel="noopener noreferrer"&gt;Pulpie&lt;/a&gt; locally to turn web pages into Markdown.&lt;/p&gt;

&lt;p&gt;It uses a small content extraction model rather than just grabbing the raw page or trying to summarize it, and I've been really impressed with the results.&lt;/p&gt;

&lt;p&gt;But there was one annoying part:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I was still the one pulling the documentation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I wanted an agent to work with a library or framework, I might grab some docs, save them into the project, point the agent toward them, and then let it work.&lt;/p&gt;

&lt;p&gt;Which is fine.&lt;/p&gt;

&lt;p&gt;But also... why am &lt;em&gt;I&lt;/em&gt; doing that?&lt;/p&gt;

&lt;p&gt;The agent has MCP tools. It knows what documentation it needs. It knows what project it's working on.&lt;/p&gt;

&lt;p&gt;So I built an MCP server that lets it do the whole thing itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What pulpie-mcp gives the agent
&lt;/h2&gt;

&lt;p&gt;There are currently four tools:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fetch_markdown&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch a page and return clean Markdown directly to the agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;save_markdown&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch a page and save it as a Markdown file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;crawl_docs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Crawl an entire documentation section and save it locally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;list_library&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check which documentation has already been saved&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The distinction between fetching and saving turned out to be especially useful.&lt;/p&gt;

&lt;p&gt;Sometimes an agent just needs to quickly read one page.&lt;/p&gt;

&lt;p&gt;Other times I'm working on a project where I want it to pull an entire section of documentation and keep it around.&lt;/p&gt;

&lt;p&gt;For example, I can basically tell Claude:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pull the uv docs into this project's DOCS/reference folder.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it handles the rest.&lt;/p&gt;

&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do we already have the FastAPI docs saved somewhere?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No elaborate prompts required.&lt;/p&gt;

&lt;h2&gt;
  
  
  It doesn't shove 60 pages into the context window
&lt;/h2&gt;

&lt;p&gt;This part was important to me.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;crawl_docs&lt;/code&gt; saves documentation, it doesn't return the contents of every page to the agent.&lt;/p&gt;

&lt;p&gt;That would be completely insane.&lt;/p&gt;

&lt;p&gt;Instead, the docs are written to disk and the agent gets useful metadata back. Each file also includes frontmatter with the source URL, title, and fetch time.&lt;/p&gt;

&lt;p&gt;So the agent can grab a whole documentation section once and then read only the files it actually needs.&lt;/p&gt;

&lt;p&gt;That turns the local filesystem into a pretty nice little documentation library.&lt;/p&gt;

&lt;p&gt;For project-specific docs, the agent can save them inside the project.&lt;/p&gt;

&lt;p&gt;For general research, pulpie-mcp has a global library at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.pulpie/library/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Crawling is actually fairly smart too
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;crawl_docs&lt;/code&gt; doesn't just blindly click every link it sees.&lt;/p&gt;

&lt;p&gt;It looks for sitemap information first:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;robots.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a sitemap under the documentation path&lt;/li&gt;
&lt;li&gt;the site's root sitemap&lt;/li&gt;
&lt;li&gt;link crawling as a fallback&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It stays on the same host and underneath the documentation path you started with.&lt;/p&gt;

&lt;p&gt;There are four concurrent crawling workers, so network requests can overlap while extraction is happening.&lt;/p&gt;

&lt;p&gt;That's how it managed to tear through those 60 pages so quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model runs locally
&lt;/h2&gt;

&lt;p&gt;This is probably my favorite part.&lt;/p&gt;

&lt;p&gt;pulpie-mcp uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feyninc/pulpie-orange-small
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's only a &lt;strong&gt;210M parameter encoder model&lt;/strong&gt;, and on my machine it uses around &lt;strong&gt;420 MB of VRAM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The MCP process itself doesn't load PyTorch or the model.&lt;/p&gt;

&lt;p&gt;Instead, there's a tiny MCP server and a separate local backend.&lt;/p&gt;

&lt;p&gt;When the agent uses one of the tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent
  ↓
MCP server
  ↓
Local Pulpie backend
  ↓
Web page
  ↓
Clean Markdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the backend isn't running yet, the MCP server starts it automatically.&lt;/p&gt;

&lt;p&gt;Once it's running, every agent session shares the same backend, so I don't end up with Claude, Codex, and whatever else I'm abusing that day each loading their own copy of the model.&lt;/p&gt;

&lt;p&gt;After 30 minutes without a request, it shuts itself down and releases the memory.&lt;/p&gt;

&lt;p&gt;That was one of those little implementation details that took this from "neat experiment" to something I can actually leave installed and forget about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding it to Claude Code
&lt;/h2&gt;

&lt;p&gt;Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv tool &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/pinkpixel-dev/pulpie-mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--scope&lt;/span&gt; user pulpie &lt;span class="nt"&gt;--&lt;/span&gt; pulpie-mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's basically it.&lt;/p&gt;

&lt;p&gt;The first time it runs, the Pulpie model downloads from Hugging Face.&lt;/p&gt;

&lt;h2&gt;
  
  
  Codex
&lt;/h2&gt;

&lt;p&gt;Add this to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.codex/config.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[mcp_servers.pulpie]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pulpie-mcp"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And other MCP clients can use a normal MCP server configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  There are still some limitations
&lt;/h2&gt;

&lt;p&gt;I haven't come across any pages that haven't worked yet, but it's possible that some completely client-rendered pages could come back empty. And it doesn't handle PDFs.&lt;/p&gt;

&lt;p&gt;I've only personally tested it on Linux with NVIDIA/CUDA so far. &lt;/p&gt;

&lt;p&gt;There is also one license note: the pulpie-mcp code is Apache 2.0, but the &lt;code&gt;pulpie-orange-small&lt;/code&gt; model is licensed &lt;strong&gt;CC BY-NC 4.0&lt;/strong&gt;, so the model is for non-commercial use unless you arrange something different with its creator.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is exactly what I want MCP to be used for
&lt;/h2&gt;

&lt;p&gt;I think that's what has me so excited about this project.&lt;/p&gt;

&lt;p&gt;MCP gets discussed a lot in terms of connecting agents to giant services and APIs.&lt;/p&gt;

&lt;p&gt;But I really like this smaller category of MCP tools:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Give the agent one very specific capability that removes a repetitive step from my workflow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the documentation.&lt;/li&gt;
&lt;li&gt;Pull the relevant pages.&lt;/li&gt;
&lt;li&gt;Clean them up.&lt;/li&gt;
&lt;li&gt;Save them somewhere.&lt;/li&gt;
&lt;li&gt;Tell the coding agent where they are.&lt;/li&gt;
&lt;li&gt;Finally start working.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now I can basically say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Grab the docs you need and figure this out.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it does.&lt;/p&gt;

&lt;p&gt;Seeing it pull &lt;strong&gt;60 pages in about 49 seconds&lt;/strong&gt;, save them as clean Markdown, build an index, and then immediately start using them was one of those wonderful little:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Oh. Damn. This is actually really useful."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;moments.&lt;/p&gt;

&lt;p&gt;And those are my favorite kinds of projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/pinkpixel-dev/pulpie-mcp" rel="noopener noreferrer"&gt;pulpie-mcp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>opensource</category>
      <category>python</category>
    </item>
    <item>
      <title>I built my husband a vim trainer with a Gemma coach that runs in the browser</title>
      <dc:creator>Jessica Doering</dc:creator>
      <pubDate>Sun, 04 Oct 2026 05:16:41 +0000</pubDate>
      <link>https://dev.to/sizzlebop/i-built-my-husband-a-vim-trainer-with-a-gemma-coach-that-runs-in-the-browser-5fmh</link>
      <guid>https://dev.to/sizzlebop/i-built-my-husband-a-vim-trainer-with-a-gemma-coach-that-runs-in-the-browser-5fmh</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;A lot of my friends build their own tools. They hit a problem and just make the thing they want. I wanted to build something for someone else this time, and the answer was sitting right next to me.&lt;/p&gt;

&lt;p&gt;My husband has wanted to learn vim for a long time. He's tried a bunch of times, and it always ends the same way: he gives up. When I asked him why, it came down to two things. There are too many commands to memorize, and everything feels slow and awkward compared to what he's used to.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;hjkl&lt;/strong&gt;, a browser app that teaches vim in tiny drills.&lt;/p&gt;

&lt;p&gt;Each drill gives you a small buffer, a goal, and a keystroke "par" to beat. You solve it in a real vim editor, not a simulation. A few things I designed around his actual problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Only a few commands at a time.&lt;/strong&gt; Each lesson introduces a small set of commands, with a cheat sheet always on screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every command shows the VS Code habit it replaces.&lt;/strong&gt; &lt;code&gt;dd&lt;/code&gt; is Ctrl+Shift+K, &lt;code&gt;o&lt;/code&gt; is Ctrl+Enter, &lt;code&gt;ciw&lt;/code&gt; is roughly Ctrl+D and type. If there isn't a real equivalent (like &lt;code&gt;.&lt;/code&gt; or &lt;code&gt;f&lt;/code&gt;), it just says so.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Par instead of pass/fail.&lt;/strong&gt; You always finish the drill. If you took the long way, you see the shorter answer right there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Review list.&lt;/strong&gt; Any drill you solved over par goes into Review, worst first, and drops off once you hit par. Those are exactly the commands that haven't stuck yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A full Vim reference.&lt;/strong&gt; The lesson cheat sheet only shows what you're currently learning, but there's also an All Commands reference with everything covered in the app. You can search it by key, action, or the VS Code shortcut you're used to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plain names under weird keys.&lt;/strong&gt; &lt;code&gt;&amp;lt;CR&amp;gt;&lt;/code&gt; shows "Enter" underneath and &lt;code&gt;&amp;lt;Esc&amp;gt;&lt;/code&gt; shows "Escape". I added this after I had to ask what &lt;code&gt;&amp;lt;CR&amp;gt;&lt;/code&gt; meant myself while testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Right now there are &lt;strong&gt;17 lessons and 124 hand-written drills&lt;/strong&gt;, starting with basic movement and insert mode and working up through text objects, counts and combos, search, visual mode, substitutions, macros, registers, and more.&lt;/p&gt;

&lt;p&gt;Then there's the AI part, which runs entirely in the browser.&lt;/p&gt;

&lt;p&gt;When I handed it over to him, he actually sat there and worked through it for a while, which felt like a pretty good sign considering every previous attempt at learning vim had ended with him giving up. He liked the short drills and being able to see the more efficient answer when he took the long way. More importantly, he kept going without me having to convince him to.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Live:&lt;/strong&gt; &lt;a href="https://hjkl.pinkpixel.dev" rel="noopener noreferrer"&gt;https://hjkl.pinkpixel.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll want a desktop browser with a physical keyboard (vim on a phone keyboard is not a good time). The AI coach needs WebGPU.&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/pinkpixel-dev" rel="noopener noreferrer"&gt;
        pinkpixel-dev
      &lt;/a&gt; / &lt;a href="https://github.com/pinkpixel-dev/hjkl" rel="noopener noreferrer"&gt;
        hjkl
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/pinkpixel-dev/hjkl/main/hjkl.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpinkpixel-dev%2Fhjkl%2Fmain%2Fhjkl.png" alt="hjkl" width="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;hjkl is a browser app for learning vim through short drills. Each drill gives you a tiny buffer, a goal, and a keystroke par to beat, and you solve it in a real vim editor.&lt;/p&gt;

&lt;p&gt;I'm building it for my husband. He's tried to learn vim a few times, but it always ends the same way: too many commands to remember, and everything feels slow and awkward compared to what his hands already know. So instead of one long tutorial, hjkl teaches two or three commands at a time, shows the VS Code style habit each one replaces, and lets you practice until it sticks.&lt;/p&gt;

&lt;p&gt;Try it at &lt;strong&gt;&lt;a href="https://hjkl.pinkpixel.dev" rel="nofollow noopener noreferrer"&gt;https://hjkl.pinkpixel.dev&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What's in it right now&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;17 lessons and 124 hand-written drills. They start with movement and insert mode, then work through word and line jumps, file jumps (&lt;code&gt;gg&lt;/code&gt;, &lt;code&gt;G&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt;, &lt;code&gt;{&lt;/code&gt;/&lt;code&gt;}&lt;/code&gt;), small fixes (…&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/pinkpixel-dev/hjkl" 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;p&gt;The app itself is Vite and plain TypeScript, no framework. The editor is CodeMirror 6 with &lt;code&gt;@replit/codemirror-vim&lt;/code&gt;, so it's real vim behavior: motions, operators, text objects, dot-repeat, registers, search.&lt;/p&gt;
&lt;h3&gt;
  
  
  Every drill is checked in real vim
&lt;/h3&gt;

&lt;p&gt;Every drill has a reference solution, and par is just its length. The test suite runs every reference solution through the actual vim engine and checks that it really produces the goal. That turned out to matter a lot. My first pass had a few pars that couldn't be hit, and the tests caught them immediately. There are 182 tests now.&lt;/p&gt;

&lt;p&gt;It also caught some fun bugs. My favorite: search drills worked fine on their own but broke after pressing Next. The vim plugin keeps search history and jump positions globally, so the second search tried to jump to a position from the previous, longer buffer and crashed. Now vim's global state resets for every drill.&lt;/p&gt;
&lt;h3&gt;
  
  
  The coach: Gemma running on your GPU
&lt;/h3&gt;

&lt;p&gt;The AI coach is optional and off by default. When you turn it on, it downloads &lt;strong&gt;Gemma 4 E2B&lt;/strong&gt; once and runs it in a Web Worker on WebGPU with &lt;strong&gt;Transformers.js&lt;/strong&gt;. Your keystrokes and prompts never leave the browser. The model files come from Hugging Face, and after that everything is local.&lt;/p&gt;

&lt;p&gt;A few details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It loads Gemma 4 through the text-only path, so it only downloads the text model and skips the vision and audio encoders.&lt;/li&gt;
&lt;li&gt;It uses &lt;code&gt;q4f16&lt;/code&gt; when the GPU supports fp16 shaders and falls back to &lt;code&gt;q4&lt;/code&gt; otherwise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 3 1B&lt;/strong&gt; is there as a lighter option you can switch to without turning the coach off.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On my machine, Gemma 4 E2B writes about 6 to 7 tokens a second, so a one-sentence explanation takes a few seconds. Gemma 3 1B is faster (about 10 tokens a second), but when I tested both on the same drills, 1B kept getting the commands wrong, and once it just greeted him instead of giving feedback. So Gemma 4 is the default.&lt;/p&gt;

&lt;p&gt;The coach does two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;After an over-par solve&lt;/strong&gt;, it explains what the shorter answer does differently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Hint button&lt;/strong&gt; nudges you toward the right command without giving away the whole sequence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Getting the feedback accurate took some work. My first version sent the model the raw keystrokes, and after a drill solved with &lt;code&gt;x&lt;/code&gt; seven times, it confidently told him he'd used &lt;code&gt;dd&lt;/code&gt;. A small model reading &lt;code&gt;xxxxxxx&lt;/code&gt; doesn't really see seven presses of one key.&lt;/p&gt;

&lt;p&gt;The fix was to stop making the model parse vim. Before the keys go into the prompt, the app groups them the way vim reads them and labels each one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x ×7 (delete character)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of &lt;code&gt;xxxxxxx&lt;/code&gt;, and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cw (change to word end), typed "blue", &amp;lt;Esc&amp;gt; (back to normal mode)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of &lt;code&gt;cwblue&amp;lt;Esc&amp;gt;&lt;/code&gt;. After that change, all of my test cases came back accurate, like: "&lt;code&gt;dw&lt;/code&gt; deletes the word under the cursor, which is much faster than deleting each character individually."&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-generated drills
&lt;/h3&gt;

&lt;p&gt;The part I'm happiest with is the &lt;strong&gt;5 more&lt;/strong&gt; button on each lesson.&lt;/p&gt;

&lt;p&gt;My first attempt let Gemma write whole drills: the text, the starting cursor, the solution keys. Only 2 of 12 drafts survived validation. The rest had missing cursor marks, keys that didn't do what the instruction said, or text glued onto other words. I kept adding filters and kept finding new kinds of mistakes.&lt;/p&gt;

&lt;p&gt;So I split the job up based on what each side is good at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma writes a short snippet&lt;/strong&gt; of text (a SQL query, a shopping list, a CSS rule), plus a short instruction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The app supplies the keys&lt;/strong&gt; by reusing the key patterns from that lesson's hand-written drills on the new text. Then it plays them in real vim to get the goal and par.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The instruction gets checked.&lt;/strong&gt; If Gemma's wording doesn't name what actually changes, the app swaps in a plain one like &lt;code&gt;Change "milk" to "eggs"&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now every batch keeps 5 out of 5, in about 15 seconds. Every generated drill is solvable at par, because the app played it before showing it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying
&lt;/h3&gt;

&lt;p&gt;It's a static site on Cloudflare Workers static assets. The only wrinkle was ONNX Runtime's wasm file, which is about 27 MB, over Cloudflare's 25 MiB per-file limit. Transformers.js already loads it from jsDelivr pinned to the exact version, so I just left it out of the build.&lt;/p&gt;

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

&lt;p&gt;For this project it's pretty concrete. An open-weight model is the reason the coach can run in his browser at all.&lt;/p&gt;

&lt;p&gt;With a closed API, every hint and every generated drill would be a paid request, plus a server and an API key to manage. For a gift that's supposed to stick around, that's a bad fit. Running Gemma locally means it costs nothing per use, it works without an account, and his keystrokes and mistakes stay on his machine.&lt;/p&gt;

&lt;p&gt;It also means I could do things a hosted API would make awkward. I picked a model size that fits a laptop GPU, compared two Gemma models side by side on the same drills, and swapped between them with one click. The rest of the stack is open too: Transformers.js, ONNX Runtime Web, CodeMirror, and the vim plugin that made "use real vim" possible in the first place.&lt;/p&gt;

&lt;p&gt;If I keep working on it, I’d like to add more lessons and keep improving the generated drills, but I also want to see what happens after he’s used it for a while. The whole point was to build something around the way one actual person was struggling to learn, so whether it really helps those commands stick is probably the best test I could give it.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Gemma&lt;/strong&gt;: the coach and the AI drill generator both run Gemma 4 E2B locally in the browser through Transformers.js on WebGPU, with Gemma 3 1B as a lighter option.&lt;/p&gt;

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