<?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: Dmytro Voytko</title>
    <description>The latest articles on DEV Community by Dmytro Voytko (@dmytrovoytko).</description>
    <link>https://dev.to/dmytrovoytko</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%2F1200779%2Fb63c32cd-a2c6-4152-a104-4e32d8ecb3a1.jpeg</url>
      <title>DEV Community: Dmytro Voytko</title>
      <link>https://dev.to/dmytrovoytko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dmytrovoytko"/>
    <language>en</language>
    <item>
      <title>🕯️ Lumina: Realms of Remembrance &amp; Lore -educational Halloween-adjacent arcade 👻</title>
      <dc:creator>Dmytro Voytko</dc:creator>
      <pubDate>Thu, 29 Oct 2026 16:04:30 +0000</pubDate>
      <link>https://dev.to/dmytrovoytko/lumina-realms-of-remembrance-lore-educational-halloween-adjacent-arcade-412d</link>
      <guid>https://dev.to/dmytrovoytko/lumina-realms-of-remembrance-lore-educational-halloween-adjacent-arcade-412d</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;🕯️ Lumina: Realms of Remembrance &amp;amp; Lore&lt;/strong&gt; is a browser-based educational trivia arcade that treats Halloween as &lt;em&gt;two&lt;/em&gt; traditions worth learning from, not one.&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%2Fa3k1fk0061lhccyj2wm6.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%2Fa3k1fk0061lhccyj2wm6.png" alt="Start Screen" width="800" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Challenge theme asked for something spooky, Halloween-adjacent, &lt;em&gt;or&lt;/em&gt; in the spirit of Día de los Muertos. I chose "all of the above" and made the duality the whole point. Lumina ships with three playable realms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;El Camino de los Recuerdos&lt;/strong&gt; — Día de los Muertos through real Nahua cosmology (&lt;em&gt;Mictlán&lt;/em&gt;, &lt;em&gt;Mictecacihuatl&lt;/em&gt;, the &lt;em&gt;Cihuateteo&lt;/em&gt;), the four elemental offerings (salt, water, copal, papel picado), the botanical chemistry of &lt;em&gt;cempasúchil&lt;/em&gt; marigolds, Posada and Rivera's &lt;em&gt;La Catrina&lt;/em&gt;, and Purepecha candlelit vigils on Lake Pátzcuaro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Alchemist's Crypt&lt;/strong&gt; — Halloween as &lt;em&gt;science&lt;/em&gt;. Samhain harvest markers, Pepper's Ghost optics and 45° specular reflection, bat echolocation and moth counter-clicks, &lt;em&gt;tapetum lucidum&lt;/em&gt; night vision, pumpkin beta-carotene, and medical debunkings of vampire and werewolf lore (&lt;em&gt;porphyria&lt;/em&gt;, ergotism, rabies).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Liminal Crossroads&lt;/strong&gt; — a hybrid mode that alternates between both, asking players to hold two cosmologies at once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core loop is a &lt;strong&gt;ticking candle survival engine&lt;/strong&gt;. An animated SVG candle is your life bar: correct answers replenish the flame, mistakes puff smoke and cost seconds, and streaks (3x/5x/10x) trigger luminous flares and harmonic fanfares. It's a game about &lt;em&gt;keeping a light alive while learning why we light it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There are &lt;strong&gt;60 pre-seeded, culturally vetted questions&lt;/strong&gt; (36 four-choice + 24 Myth-vs-Fact), three difficulty tiers, a Certificate of Luminous Attainment gated at 50% with printable/PDF export, a "Knowledge Digest" session recap, and an in-app &lt;strong&gt;Codex Explorer&lt;/strong&gt; for reading every fact outside of gameplay.&lt;/p&gt;

&lt;p&gt;I wanted the "spooky" to be the hook and the education to be the payload — the scariest thing in Lumina is how much of the folklore turns out to be chemistry, biology, and history.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://dmytrovoytko.github.io/lumina-spookyedu/" rel="noopener noreferrer"&gt;https://dmytrovoytko.github.io/lumina-spookyedu/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trivia &amp;amp; candle timer&lt;/li&gt;
&lt;/ul&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%2Fv8vp89lyaqts1qcd6618.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%2Fv8vp89lyaqts1qcd6618.png" alt="Trivia &amp;amp; candle timer" width="690" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Candle pressure &amp;amp; time limits&lt;/li&gt;
&lt;/ul&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%2Fznrnayxmef0evme6co52.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%2Fznrnayxmef0evme6co52.png" alt="Candle pressure &amp;amp; time limits" width="677" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Knowledge base - Codex of Remembrance &amp;amp; Science&lt;/li&gt;
&lt;/ul&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%2Fi8ugevghc7ixpyd0uhmk.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%2Fi8ugevghc7ixpyd0uhmk.png" alt="Knowledge base - Codex of Remembrance &amp;amp; Science" width="685" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certificate of Luminous Attainment&lt;/li&gt;
&lt;/ul&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%2Fhtldhhkewh4whygcw0hv.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%2Fhtldhhkewh4whygcw0hv.png" alt="Certificate of Luminous Attainment" width="788" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The demo runs fully offline on GitHub Pages — no backend, no login, no API key required.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/dmytrovoytko/lumina-spookyedu" rel="noopener noreferrer"&gt;github.com/dmytrovoytko/lumina-spookyedu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Highlights worth a look:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/components/AIQuestionGeneratorModal.tsx&lt;/code&gt; — optional LLM question generation with a local fallback synthesizer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/components/CandleHUD.tsx&lt;/code&gt; — the SVG candle survival/timer engine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/data/triviaBank.ts&lt;/code&gt; — the 60 vetted Día de los Muertos / Halloween science questions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/utils/audio.ts&lt;/code&gt; — the procedural Web Audio sound design (zero audio files).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.github/workflows/&lt;/code&gt; — static build + GitHub Pages deploy.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; React 19 + TypeScript, Tailwind CSS v4, Vite, Lucide React, and the native &lt;strong&gt;Web Audio API&lt;/strong&gt;. It builds to a 100% static bundle with 16 unit tests via &lt;code&gt;tsx --test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The open-weight model:&lt;/strong&gt; Lumina's content is pre-seeded and offline-first, but the &lt;strong&gt;Infinite AI Question Generator&lt;/strong&gt; lets players expand the deck on demand. When a user supplies an API key, it calls an open-weight &lt;strong&gt;Gemma&lt;/strong&gt; model — &lt;code&gt;gemma-4-31b-it&lt;/code&gt; in the current build (swappable for &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; or &lt;code&gt;gemini-3.5-flash&lt;/code&gt; via a single line in &lt;code&gt;AIQuestionGeneratorModal.tsx&lt;/code&gt;). The prompt asks the model to return strict JSON trivia cards with an explanation and a source/context field, so generated content stays in the same educational format as the curated bank.&lt;/p&gt;

&lt;p&gt;The important design choice: &lt;strong&gt;the model is an enhancement, never a dependency.&lt;/strong&gt; If there's no key, no network, or the request fails, the app falls back to a local procedural synthesizer, so the GitHub Pages demo stays fully functional. That's deliberate — an educational artifact shouldn't break because an API quota did.&lt;/p&gt;

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

&lt;p&gt;Open innovation made the &lt;em&gt;shape&lt;/em&gt; of this project possible, not just its cost.&lt;/p&gt;

&lt;p&gt;First, &lt;strong&gt;open-weight models let me put a frontier-ish model behind a static site&lt;/strong&gt; with no proprietary backend and no vendor lock-in. A visitor can bring their own key, or none at all, and the experience degrades gracefully. That portability is only possible because the model is open and callable on my terms.&lt;/p&gt;

&lt;p&gt;Second, &lt;strong&gt;open tooling made the whole thing reproducible&lt;/strong&gt;: Vite, React, Tailwind, the Web Audio API, and a GitHub Actions workflow mean anyone can fork Lumina, change a question, swap the model, and redeploy to their own Pages URL. A closed-API product would have locked the content pipeline behind someone else's dashboard.&lt;/p&gt;

&lt;p&gt;Third, and most importantly for this theme: &lt;strong&gt;cultural knowledge should be inspectable and remixable.&lt;/strong&gt; Día de los Muertos is living heritage, and the best guard against flattening it into decoration is a codebase where the sources, explanations, and question logic are all visible and editable. Open source lets educators, families, and communities correct and extend the material — which a black-box API never could.&lt;/p&gt;

&lt;p&gt;Lumina is my small argument that spooky and sacred can share a candle 🕯️ and that the light should belong to everyone.&lt;/p&gt;

&lt;p&gt;🎃💀 Have fun! 👻&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Smart Feed Filter: Tuning My RSS Digest with a Local JEV-like model in Ollama</title>
      <dc:creator>Dmytro Voytko</dc:creator>
      <pubDate>Sun, 25 Oct 2026 18:39:33 +0000</pubDate>
      <link>https://dev.to/dmytrovoytko/smart-feed-filter-tuning-my-rss-digest-with-a-local-jev-like-model-in-ollama-827</link>
      <guid>https://dev.to/dmytrovoytko/smart-feed-filter-tuning-my-rss-digest-with-a-local-jev-like-model-in-ollama-827</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Smart Feed Filter&lt;/strong&gt; turns public RSS feeds into a short, category-grouped digest for one person.&lt;/p&gt;

&lt;p&gt;The problem: professionals with RSS still drown in unread items, and generic readers sort by recency while AI summarizers add reading work instead of removing it.&lt;/p&gt;

&lt;p&gt;Smart Feed Filter removes the triage step. You define a profile: a small set of categories, each with a name, description, criteria, and weight. A local decision model scores every feed item against those categories. The app shows the last 72 hours grouped by category, ranked inside each category, with tags and (optionally) a one-line reason.&lt;/p&gt;

&lt;p&gt;It's a filtering engine, not a summarizer. No article fetching, no private accounts, no generated prose.&lt;/p&gt;

&lt;p&gt;Who gets a little more relaxed, or lazier? The data scientist who wants to skim only ML-method papers and skip hiring/funding noise; the off-work reader who wants hobby content without the feed becoming an everything feed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow
&lt;/h2&gt;

&lt;p&gt;Smart Feed Filter's workflow in two steps: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the user defines a profile of weighted categories with plain-language criteria, &lt;/li&gt;
&lt;li&gt;then hits refresh to fetch and dedupe public RSS feeds while a local Ollama decision model scores each new item against the enabled categories, producing a 72-hour digest grouped and ranked by category.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User defines profile (categories, criteria, weights)
        │
        ▼
Manual refresh → fetch → dedupe → store
        │
        ▼
Local classifier (Ollama) scores new items
        │
        ▼
72h digest grouped by category, ranked by score
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Here are screenshots of the running app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smart Feed categorization processing&lt;/li&gt;
&lt;/ul&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%2F12sikm5h8emgojcyyud4.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%2F12sikm5h8emgojcyyud4.png" alt="Smart Feed categorization processing" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digest grouped by category, ranked items with match confidence&lt;/li&gt;
&lt;/ul&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%2F9cgt32d2be4kl38c08ky.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%2F9cgt32d2be4kl38c08ky.png" alt="Digest grouped by category, ranked items with match confidence" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digest grouped by category, collapsed, including &lt;code&gt;Low confidence&lt;/code&gt; group and sources&lt;/li&gt;
&lt;/ul&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%2Fxm5r4qr1s5r3as5g97kk.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%2Fxm5r4qr1s5r3as5g97kk.png" alt="Digest grouped by category, collapsed" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/dmytrovoytko/rss-smart-feed-filter" rel="noopener noreferrer"&gt;GitHub repo structure&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── app
│   ├── config.py
│   ├── db.py
│   ├── __init__.py
│   ├── logging_config.py
│   ├── __main__.py
│   ├── main.py
│   ├── routes/
│   ├── schema.sql
│   ├── seed.py
│   ├── services/
│   ├── static/
│   ├── templates/
│   ├── timeutil.py
│   └── versioning.py
├── data
│   └── feedfilter.db
├── eval/
├── profiles
│   ├── catalog.yaml
│   ├── ds.v1.yaml
│   └── fun.v1.yaml
├── pyproject.toml
├── requirements.txt
├── spec.md
└── tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Python 3.12+, FastAPI, Jinja2 + HTMX, SQLite WAL, feedparser, requests, PyYAML, pydantic, python-dateutil, uvicorn.&lt;/li&gt;
&lt;li&gt;Local decision model via Ollama: model &lt;code&gt;tev1:0.8b&lt;/code&gt; (fallback &lt;code&gt;tev1:4b&lt;/code&gt;), POST /v1/systemone. &lt;/li&gt;
&lt;li&gt;State = title + summary, truncated to 1200 chars word boundary; no article fetching; no HTML.&lt;/li&gt;
&lt;li&gt;One noul question per enabled category per item; up to 16 categories.&lt;/li&gt;
&lt;li&gt;Threshold by profile, 0.55 default; match when probability ≥ threshold; low confidence collapsed by default.&lt;/li&gt;
&lt;li&gt;Ranking: probability × weight × recency decay; 72h window; dedupe canonical URL + normalized title; retention 30 days.&lt;/li&gt;
&lt;li&gt;Retroactive edits: preview re-scores last 14 days, atomic apply, cancel discards.&lt;/li&gt;
&lt;li&gt;Error handling: persisted job state, actionable banner (&lt;code&gt;ollama serve&lt;/code&gt;, &lt;code&gt;ollama pull tev1:0.8b&lt;/code&gt;), retry classifies only missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reasons are templated, never generated. Ranking handles ordering. Retroactive edits use a preview-diff-then-atomic-apply flow over the last 14 days; weight edits reorder without model calls, threshold edits re-filter cached probabilities.&lt;/p&gt;

&lt;p&gt;Before building UI, I ran a model gate via &lt;code&gt;python eval/harness.py --gate&lt;/code&gt;: a 100-item labeled set (50 per profile) scored on macro-F1, precision@10, latency, and failures. The local &lt;code&gt;tev1:0.8b&lt;/code&gt; model passed my selection after category and threshold tuning; fallback &lt;code&gt;tev1:4b&lt;/code&gt; documented.&lt;/p&gt;

&lt;h3&gt;
  
  
  The hard part
&lt;/h3&gt;

&lt;p&gt;Categorizing work content was (is?) harder than off-work (fun) content because real-world topics overlap heavily (ML methods vs. LLM apps vs. MLOps vs. experimentation), which is exactly why the spec encodes separate criteria fields and why &lt;code&gt;ds.v1&lt;/code&gt; needed more tuning cycles than the fun profile.&lt;/p&gt;

&lt;p&gt;Here is the sample of &lt;code&gt;ds.v1&lt;/code&gt; profile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ds.v1&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Data Scientist&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;work&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.62&lt;/span&gt;
&lt;span class="na"&gt;max_categories&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;
&lt;span class="na"&gt;seed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;Professional reading profile for data scientists and ML practitioners.&lt;/span&gt;
  &lt;span class="s"&gt;Prefers methods, production practice, analytics, and responsible AI over&lt;/span&gt;
  &lt;span class="s"&gt;general technology news, hiring, funding, and product marketing.&lt;/span&gt;
&lt;span class="na"&gt;exclude_hints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;hiring, recruiting, and career advice&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;funding, acquisitions, and business news&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;consumer gadgets and general technology policy&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;health or medical advice&lt;/span&gt;
&lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ml-research&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ML Methods &amp;amp; Research&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;New machine-learning methods, architectures, training techniques,&lt;/span&gt;
      &lt;span class="s"&gt;benchmarks, or results from research papers and research labs.&lt;/span&gt;
    &lt;span class="na"&gt;criteria_true&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;The item reports or analyzes a machine-learning method, model, benchmark,&lt;/span&gt;
      &lt;span class="s"&gt;training technique, or research finding.&lt;/span&gt;
    &lt;span class="na"&gt;criteria_false&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;The item is product news, production operations, business news, career&lt;/span&gt;
      &lt;span class="s"&gt;advice, or not about machine-learning methods.&lt;/span&gt;
    &lt;span class="na"&gt;reason_hint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;covers methods, architectures, benchmarks, or research findings&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.3&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each category can be enabled/disabled. So for example you can be interested in some topic like "Responsible AI &amp;amp; Evaluation", and after getting enough valuable information just turn it off - until you need it again. Similarly with job search and vacancies - your &lt;code&gt;job-search&lt;/code&gt; profile can include categories for different positions with their own criteria.&lt;/p&gt;

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

&lt;p&gt;Open innovation made this build possible in a way a closed API never could. The intelligence here isn't a black box you call — it's a local model plus an open taxonomy loop: versioned category criteria, eval harness, gate, threshold tuning, and preview diffs. Opening the criteria (&lt;code&gt;criteria_true&lt;/code&gt; / &lt;code&gt;criteria_false&lt;/code&gt;, reason hints) meant the taxonomy itself became community- and maintainer-editable, versioned via hash.&lt;/p&gt;

&lt;p&gt;And because the model runs locally on an open-weight model via Ollama - local-first means no vendor lock-in. Privacy wasn't an afterthought — it was the architecture: no API key, no telemetry, nothing leaving the machine except public feed requests. Open source made that stack reproducible.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>🎬 YouTube Insight Extractor</title>
      <dc:creator>Dmytro Voytko</dc:creator>
      <pubDate>Mon, 19 Oct 2026 06:43:05 +0000</pubDate>
      <link>https://dev.to/dmytrovoytko/youtube-insight-extractor-125m</link>
      <guid>https://dev.to/dmytrovoytko/youtube-insight-extractor-125m</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Long-form YouTube is where the best ideas live — Tim Ferriss, Huberman, Diary of a CEO — but a two-to-three-hour interview buries a handful of personally relevant insights inside hours of conversation. Watching the whole thing to find them is why people give up.&lt;/p&gt;

&lt;p&gt;YT Insight Extractor turns a YouTube link into a focused, timestamped action plan. You paste a URL, pick an &lt;strong&gt;Area of Life&lt;/strong&gt; (Career, Fitness, Finance, Productivity…), and optionally describe a goal. The app returns two tabs — &lt;strong&gt;subtopic summaries&lt;/strong&gt; and &lt;strong&gt;actionable ideas&lt;/strong&gt; — each anchored to a clickable timestamp that jumps to the exact moment in the video. Results export to Markdown or JSON and are saved to a local history with 👍/👎 feedback.&lt;/p&gt;

&lt;p&gt;Who would pay for it? Self-directed learners, coaches, and creators who consume hours of long-form content weekly and want signal, not another bookmark.&lt;/p&gt;

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

&lt;p&gt;No public deployment — deliberate. YouTube blocks cloud-provider IPs, so a hosted demo would fail at the transcript step. Instead the repo ships a local-first app you run yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Insights&lt;/strong&gt; — staged pipeline UI (&lt;code&gt;extract transcript → chunk &amp;amp; vectorize → RAG &amp;amp; summarize&lt;/code&gt;) with per-step status, then the two result tabs with clickable timestamps.&lt;/li&gt;
&lt;/ul&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%2Fevote11ajkcrwvrluowl.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%2Fevote11ajkcrwvrluowl.png" alt="Insights page" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Configuration&lt;/strong&gt; — switch LLM provider at runtime (local Ollama default; BYOK cloud optional).&lt;/li&gt;
&lt;/ul&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%2Fqd6h6n1gwq5yjx1zc9dx.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%2Fqd6h6n1gwq5yjx1zc9dx.png" alt="Configuration page" width="788" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;History&lt;/strong&gt; — every run saved locally, with feedback buttons.&lt;/li&gt;
&lt;/ul&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%2Fienu8fvyxua2u1k6q7u3.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%2Fienu8fvyxua2u1k6q7u3.png" alt="History page" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Report Dashboard&lt;/strong&gt; — usage KPIs: runs, goals, latency, distributions by area, LLM, and feedback.&lt;/li&gt;
&lt;/ul&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%2Fw00vdltv526v13d3yxhq.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%2Fw00vdltv526v13d3yxhq.png" alt="Report dashboard" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/dmytrovoytko/llm-yt-insight-extractor" rel="noopener noreferrer"&gt;YT Insight Extractor repo on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.py&lt;/code&gt; orchestrates &lt;code&gt;core/&lt;/code&gt;, with each pipeline stage a small, independently testable module: &lt;code&gt;core/rag_engine.py&lt;/code&gt; (retrieval), &lt;code&gt;core/hybrid.py&lt;/code&gt; (RRF fusion), &lt;code&gt;core/generator.py&lt;/code&gt; (schema-constrained output), &lt;code&gt;core/prompts.py&lt;/code&gt; (v1/v2 prompts), plus offline evals in &lt;code&gt;scripts/&lt;/code&gt;. Tests: &lt;code&gt;python -m unittest discover -s tests/&lt;/code&gt; (200 tests).&lt;/p&gt;

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

&lt;p&gt;The stack is open-source end to end. &lt;strong&gt;Embeddings&lt;/strong&gt;: ONNX &lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt; via &lt;code&gt;onnxruntime&lt;/code&gt; — chosen over &lt;code&gt;sentence-transformers&lt;/code&gt; to avoid ~800 MB of PyTorch and stay runnable on a CPU laptop in a small container. &lt;strong&gt;Vector store&lt;/strong&gt;: in-memory ChromaDB wrapped by LlamaIndex. &lt;strong&gt;Generation&lt;/strong&gt;: schema-constrained output via Pydantic, defaulting to local &lt;strong&gt;Ollama &lt;code&gt;llama3.2:1b&lt;/code&gt;&lt;/strong&gt;, plus BYOK cloud models. &lt;strong&gt;Retrieval&lt;/strong&gt;: &lt;code&gt;vector | keyword | hybrid&lt;/code&gt;, where hybrid uses reciprocal-rank fusion written with the standard library — no new dependencies.&lt;/p&gt;

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

&lt;p&gt;Every meaningful constraint here was solvable &lt;em&gt;only&lt;/em&gt; with open tooling. A closed API can't be pointed at a local Ollama model, can't ship ONNX weights instead of a torch dependency, and can't run entirely on your machine — no transcript, goal, or output leaving your laptop. When YouTube closed its public endpoints, the project didn't die; it adapted, because I owned the retrieval layer, not just a prompt. And because the models and evals are open, anyone can reproduce the numbers.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>🧭 StrideHunter: transform daily walks and runs into quests</title>
      <dc:creator>Dmytro Voytko</dc:creator>
      <pubDate>Sun, 11 Oct 2026 22:40:04 +0000</pubDate>
      <link>https://dev.to/dmytrovoytko/stridehunter-transform-daily-walks-and-runs-into-quests-1hio</link>
      <guid>https://dev.to/dmytrovoytko/stridehunter-transform-daily-walks-and-runs-into-quests-1hio</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;&lt;strong&gt;StrideHunter&lt;/strong&gt; is a free, open, install-free scavenger hunt PWA. An organizer (parent, teacher, team lead — or just you, for yourself) describes a place, picks walk/run, effort level, and quiz count, and gets a complete outdoor quest: point-tiered missions (50/150/300), POI quiz stops with typo-tolerant answers, a 500-pt golden finale, countdown with speed bonus. Players scan one QR code — no account, no app install — and go outside to play it.&lt;/p&gt;

&lt;p&gt;It's for three cravings I kept seeing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;desk workers who sit all week and need a reason to move, &lt;/li&gt;
&lt;li&gt;hosts who want to take a crew outside without planning for hours, and &lt;/li&gt;
&lt;li&gt;teen squads who'll go anywhere if it's a game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The phone becomes a compass, not a couch: missions only resolve out there — photos at viewpoints, quiz answers in front of statues, GPS check-ins at bonus stops.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose your effort&lt;/strong&gt;: Chill / Normal / Beast, plus &lt;em&gt;walk&lt;/em&gt; / &lt;em&gt;run&lt;/em&gt; modes and time-of-day adaptation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI quest generation&lt;/strong&gt; (BYOK OpenRouter or local Ollama): point tiers 50/150/300/500, golden mission, POI quiz stops with lenient typo-tolerant answers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outdoor-proof play&lt;/strong&gt;: GPS “you’re close” hints with honor fallback, countdown + speed bonus, offline PWA after first load&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honest sharing&lt;/strong&gt;: the link carries the whole quest (capped, trimmed, QR-friendly); draft → edit gate → publish flow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy-first&lt;/strong&gt;: no accounts, no analytics; hunt data lives in the link, API keys stay in your browser (session-only unless you opt in)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generate&lt;/th&gt;
&lt;th&gt;Dark theme, mobile&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&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%2Fa28068rr1z7buh6vy8ke.png" alt="Generate tab with a filled quest form" width="521" height="665"&gt;&lt;/td&gt;
&lt;td&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%2Fiwo76wx6j364jvmnhwbh.png" alt="Share tab with QR stage and draft tag" width="323" height="642"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Live demo&lt;/strong&gt;: &lt;a href="https://dmytrovoytko.github.io/StrideHunter/" rel="noopener noreferrer"&gt;StrideHunter app&lt;/a&gt; is deployed via GitHub Pages.&lt;/p&gt;

&lt;p&gt;Try the zero-setup demo hunt first — no key needed - just scroll to the bottom and click "&lt;strong&gt;Try demo instead&lt;/strong&gt;" button.&lt;/p&gt;

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

&lt;p&gt;GitHub repo: &lt;a href="https://github.com/dmytrovoytko/StrideHunter" rel="noopener noreferrer"&gt;🧭 StrideHunter&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;index.html        tabs (Generate / Share / Play) + settings drawer
css/style.css     theme vars, dark mode, 44px touch targets
js/app.js         everything (~1200 lines, plain scripts, zero build)
js/prompts.js     prompt templates (effort/quiz/weather/fallback branches)
sw.js             offline PWA (dev default OFF)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The core trick is the share link — the &lt;em&gt;entire quest&lt;/em&gt; lives in the URL hash, so there's no backend to run.&lt;/p&gt;

&lt;p&gt;And the AI output is never trusted blindly: JSON is extracted from plain model text, validated, organizer-approved in a preview gate — plus an &lt;code&gt;unverified&lt;/code&gt; flag (gated in code, so models can't self-apply it) marks anything the AI guessed while map data was down.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open-weight models, BYOK style:&lt;/strong&gt; generation runs on open models ( google/gemma-4-31b-it, or free Nemotron) through OpenRouter with your own free key — or fully local via Ollama. Deliberately &lt;em&gt;no&lt;/em&gt; structured-outputs requirement: the app parses JSON out of plain text, so any instruction-following model works, free or paid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-build vanilla JS&lt;/strong&gt; on free static hosting (GitHub Pages): no framework, no bundler, no server. If it can't be served from a static folder, it doesn't ship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open data instead of a POI vendor:&lt;/strong&gt; OpenStreetMap (Overpass/Nominatim) + Open-Meteo, with endpoint fallbacks, caching, and request politeness baked in after real-world 504s taught us respect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open libraries, vendored:&lt;/strong&gt; QR encoder, confetti — pinned locally, working offline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open process:&lt;/strong&gt; prompt templates live in the repo, no telemetry, tracking, etc.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Honestly? This project exists &lt;em&gt;because&lt;/em&gt; everything was open. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No budget meant no POI vendor — OSM's free data plus three public mirrors (with fallbacks I only needed because they were transparent about their limits) replaced a contract.&lt;/li&gt;
&lt;li&gt;No AI budget meant BYOK open-weights instead of a platform lock-in — and designing for “any model that emits JSON” made the app more robust than a single-model integration would be.&lt;/li&gt;
&lt;li&gt;No backend budget meant inventing the self-contained share link, which turned into the best feature: private-by-architecture (your hunt never touches my server, because there isn't one), offline-capable, and forkable by anyone — clone the repo, serve the folder, run the demo with zero keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Openness wasn't the theme of this build. It was the building material.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Flashcard Pro — DP-600 Exam Trainer</title>
      <dc:creator>Dmytro Voytko</dc:creator>
      <pubDate>Mon, 05 Oct 2026 06:56:45 +0000</pubDate>
      <link>https://dev.to/dmytrovoytko/flashcard-pro-dp-600-exam-trainer-2fdd</link>
      <guid>https://dev.to/dmytrovoytko/flashcard-pro-dp-600-exam-trainer-2fdd</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;&lt;strong&gt;Flashcard Pro — DP-600 Exam Trainer&lt;/strong&gt;, built for my friend &lt;strong&gt;Den&lt;/strong&gt; who is preparing for the &lt;strong&gt;Microsoft DP-600: Implementing Analytics Solutions Using Microsoft Fabric&lt;/strong&gt; exam.&lt;/p&gt;

&lt;p&gt;Den was drowning in Fabric docs — lakehouses, warehouses, KQL, DAX, governance — with no good way to do active recall. So I built him a simple Flask study app:&lt;/p&gt;

&lt;p&gt;Pick a mode + topic → see a term → try to recall → reveal definition → self-grade Yes/No → next card.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;202 cards across all 8 DP-600 topics, in one merged &lt;code&gt;flashcards.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modes: Any / New / Incorrect / &lt;code&gt;simple&lt;/code&gt; / &lt;code&gt;intermediate&lt;/code&gt; / &lt;code&gt;advanced&lt;/code&gt; + per-topic filter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/stats&lt;/code&gt; dashboard: accuracy overall, by topic, by difficulty&lt;/li&gt;
&lt;li&gt;JSON file storage, no DB, runs locally in 10 seconds&lt;/li&gt;
&lt;li&gt;Results log with auto-compaction + 7 unit tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Problem it solves: turns passive reading into spaced, self-tested review — especially re-drilling the cards he gets wrong.&lt;/p&gt;

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

&lt;p&gt;Live local run: &lt;code&gt;pip install -r requirements.txt &amp;amp;&amp;amp; python app.py&lt;/code&gt; → &lt;a href="http://127.0.0.1:8001/" rel="noopener noreferrer"&gt;http://127.0.0.1:8001/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshots instead of video:&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%2Fju65clyeybhmt98z6ne1.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%2Fju65clyeybhmt98z6ne1.png" alt="Home - mode + topic picker" width="542" height="470"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Home: mode + topic picker with progress summary&lt;/em&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%2F6b5p4ly41lw2i01ri7ng.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%2F6b5p4ly41lw2i01ri7ng.png" alt="Quiz - recall flow" width="800" height="425"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Quiz: term → Show Definition → Yes/No self-grade&lt;/em&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%2Fv40vfsnhqe0dp2znxz1g.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%2Fv40vfsnhqe0dp2znxz1g.png" alt="Stats dashboard" width="699" height="689"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Stats: overall / by-topic / by-difficulty accuracy&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Full flow: Home → Start Study (e.g. &lt;code&gt;incorrect&lt;/code&gt; + Topic 5) → Quiz loop → Session Complete! → Stats.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/dmytrovoytko/flashcards" rel="noopener noreferrer"&gt;https://github.com/dmytrovoytko/flashcards&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stack: Python + Flask + Jinja + Bootstrap 5, &lt;code&gt;app.py&lt;/code&gt; for routes/session, &lt;code&gt;data_manager.py&lt;/code&gt; for filtering/stats/compaction, &lt;code&gt;templates/index.html&lt;/code&gt;, &lt;code&gt;quiz.html&lt;/code&gt;, &lt;code&gt;stats.html&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Built agentically with &lt;strong&gt;open-source AI&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; google/gemma-4-31b-it — used for codebase analysis, spec writing, and implementation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harness:&lt;/strong&gt; OpenCode coding agent — Task/Todo-driven edits, test runs, verification via &lt;code&gt;python -m unittest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frameworks:&lt;/strong&gt; Flask 3, Bootstrap 5.3, stdlib &lt;code&gt;json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local-first:&lt;/strong&gt; all inference-assisted coding + all app data runs locally — cards, topics, and &lt;code&gt;results.json&lt;/code&gt; never leave the machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AI did what it's best at: brainstormed the specs and made key decisions, generated flashcards by topics and difficulty (&lt;code&gt;simple/intermediate/advanced&lt;/code&gt; in data), merged &lt;code&gt;flashcards1-8.json&lt;/code&gt; → &lt;code&gt;flashcards.json&lt;/code&gt;, fixed the filter, then implemented the suggested roadmap: topic picker, &lt;code&gt;/stats&lt;/code&gt;, &lt;code&gt;/end&lt;/code&gt;, stale-ID skipping, &lt;code&gt;SECRET_KEY&lt;/code&gt;/&lt;code&gt;FLASK_DEBUG&lt;/code&gt;/&lt;code&gt;PORT&lt;/code&gt; env config, &lt;code&gt;requirements.txt&lt;/code&gt;, and &lt;code&gt;test_data_manager.py&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;This project only works because it's open:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Forkable study content:&lt;/strong&gt; anyone can PR new cards for DP-700, AZ-104, etc. A closed API with proprietary quizzes wouldn't allow that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspectable learning logic:&lt;/strong&gt; Den can read &lt;code&gt;get_filtered_cards()&lt;/code&gt; and &lt;code&gt;get_stats()&lt;/code&gt; and trust how "incorrect" and accuracy are computed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hostable + private:&lt;/strong&gt; exam prep progress stays in a local &lt;code&gt;results.json&lt;/code&gt;, no tracking, no subscription — perfect for Hacktoberfest-style community contributions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open models → open builders:&lt;/strong&gt; I could reproduce this entire workflow with an open-weight assistant in OpenCode, iterate locally, and push back to GitHub for others to reuse.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open innovation turned a one-off favor for Den into a template anyone can clone for any certification.&lt;/p&gt;

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