<?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>Forem: austin amento</title>
    <description>The latest articles on Forem by austin amento (@austin_amento_860aebb9f55).</description>
    <link>https://forem.com/austin_amento_860aebb9f55</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1748998%2F512485ea-8fa4-4689-8607-e67307c29277.png</url>
      <title>Forem: austin amento</title>
      <link>https://forem.com/austin_amento_860aebb9f55</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/austin_amento_860aebb9f55"/>
    <language>en</language>
    <item>
      <title>The Dev Journal That Writes Itself (And Gives You XP)</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Sun, 22 Mar 2026 21:40:50 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/the-dev-journal-that-writes-itself-and-gives-you-xp-4232</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/the-dev-journal-that-writes-itself-and-gives-you-xp-4232</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/notion-2026-03-04"&gt;Notion MCP Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Every developer has a graveyard of half-remembered side projects.&lt;/p&gt;

&lt;p&gt;You know the feeling. Someone asks "what have you been building?" during a job search and you blank. Or you're writing a performance review and can't reconstruct what you shipped in Q1. Or you're three months into learning to code and can't tell if you're getting better, which honestly stings more than the other two.&lt;/p&gt;

&lt;p&gt;The problem isn't that you aren't building. It's that the work disappears into git history the moment it's committed.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;DevPulse&lt;/strong&gt; to fix that. And then I turned your git history into a game.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;DevPulse&lt;/strong&gt; is a global &lt;a href="https://claude.ai/code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; agent that automatically logs your coding sessions to Notion after every commit. It tracks your growth with XP and levels, maintains daily streaks, runs a 25-quest achievement system, and unlocks 30 achievement badges — all triggered by a single slash command, from any project on your machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🎮 Async Queue System for Ad Insertion Engine

⚡ 100 base × 1.5 (7-day streak) × 1.25 (diff run) + 10 (daily spark) + 50 (Ship It quest) = 247 XP
📊 Total: 1,847 XP

🏆 Level: Senior Dev → Staff Engineer 🎉

🔥 Streak: 8 days

🏅 Badges Unlocked:
  - Week Warrior ⚡ (7-day streak!)
  - Challenge Accepted ⚔️

⚔️ Quest Completed:
  - Challenge Accepted (50 XP) — 2 sessions this week at Difficulty 4+

• Built async-safe queue with retry logic and exponential backoff — no dropped frames under load
• Logged to Master Dev Log · Profile updated: 14 sessions, 1,847 XP, Staff Engineer
• Quests DB updated: Challenge Accepted → Completed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No server. No backend to maintain. No manual journaling. You committed your code — DevPulse reads the diff and handles everything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who It's Actually For
&lt;/h3&gt;

&lt;p&gt;I designed this for two people simultaneously, because I think they have the same core problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you're learning to code:&lt;/strong&gt; DevPulse makes the invisible visible. Every session logged is proof of work — proof that you showed up and built something. The difficulty ratings go from 1 (config tweaks) to 5 (complex algorithms). You watch them climb as you grow. Your first month might be all 2s and 3s. Six months later you're cracking 4s and 5s and the XP reflects it. The streak system is the most important feature here: building the habit of shipping daily, even small things, is what separates developers who grow fast from those who plateau. And when you can't articulate what you've been working on? Pull up your weekly recap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you're an experienced developer:&lt;/strong&gt; You already know how fast projects blur together. DevPulse gives you a structured, searchable record across every project on your machine — filtered by stack, sorted by difficulty, summarized weekly. The weekly recap generates a &lt;strong&gt;Growth Narrative&lt;/strong&gt; written from your actual data, not generic encouragement. It's also genuinely useful for performance reviews, resume updates, and the "so what have you been working on?" questions you get in every technical conversation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Growth Narrative
&lt;/h3&gt;

&lt;p&gt;This is the feature I'm most proud of. Every &lt;code&gt;/weekly-recap&lt;/code&gt; generates a Claude-written analysis of your actual week — specific to your data:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Backend-heavy week — 4 of 5 sessions touched the database layer and your average difficulty climbed to 3.8, up from 2.6 last week. TypeScript was your most-used technology for the third week running. You logged sessions on 5 different days, your most consistent week yet. Next week: your streak hits 14 days — push for Streak Legend."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not templated. That's Claude reading your Master Dev Log, spotting the pattern, and writing it back to you. It's a mirror that shows you your own growth in a way raw git logs never could.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;

&lt;p&gt;The system runs as a &lt;strong&gt;global Claude Code configuration&lt;/strong&gt; — installed once to &lt;code&gt;~/.claude/&lt;/code&gt;, active in every project on your machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/.claude/
├── CLAUDE.md                    ← DevPulse identity + XP formula + all 30 badge definitions
└── commands/
    ├── pulse-check.md           ← /pulse-check workflow &lt;span class="o"&gt;(&lt;/span&gt;11 sequential steps&lt;span class="o"&gt;)&lt;/span&gt;
    ├── weekly-recap.md          ← /weekly-recap workflow
    └── monthly-recap.md         ← /monthly-recap workflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you type &lt;code&gt;/pulse-check&lt;/code&gt;, Claude loads the agent identity from &lt;code&gt;CLAUDE.md&lt;/code&gt; and executes the 11-step workflow in &lt;code&gt;pulse-check.md&lt;/code&gt;. Every operation that touches persistent state goes through Notion MCP — there is no other storage layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Four Notion Databases
&lt;/h3&gt;

&lt;p&gt;DevPulse manages four databases entirely through MCP:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Database&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Master Dev Log&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One row per session — title, stack, difficulty, XP, commit hash, badges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DevPulse Profile&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single-row state machine: streak, total XP, level, all badges earned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DevPulse Quests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;25 quests (13 weekly rotating + 12 permanent milestones)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DevPulse Recaps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Weekly and monthly recap pages with tech breakdown + growth narrative&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three of these are &lt;strong&gt;auto-created on first run&lt;/strong&gt;. The one you set up manually (Master Dev Log) is the source of truth — DevPulse never deletes or modifies rows in it after they're written.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Full Gamification Engine (V2)
&lt;/h3&gt;

&lt;p&gt;I started with V1 (basic logging + 7 badges) and iterated to a full gamification system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;XP Multiplier Formula:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight mathematica"&gt;&lt;code&gt;&lt;span class="nv"&gt;Session&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;XP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;Difficulty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;×&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;×&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;streak&lt;/span&gt;&lt;span class="o"&gt;_&lt;/span&gt;&lt;span class="nv"&gt;mult&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;×&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;diff&lt;/span&gt;&lt;span class="o"&gt;_&lt;/span&gt;&lt;span class="nv"&gt;run&lt;/span&gt;&lt;span class="o"&gt;_&lt;/span&gt;&lt;span class="nv"&gt;mult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;daily&lt;/span&gt;&lt;span class="o"&gt;_&lt;/span&gt;&lt;span class="nv"&gt;spark&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;_&lt;/span&gt;&lt;span class="nv"&gt;bonus&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;streak_mult&lt;/code&gt;: 1.5× at 7-day streak, 2× at 30 days — consistency is rewarded&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;diff_run_mult&lt;/code&gt;: 1.25× when two back-to-back sessions hit Difficulty ≥ 4 — keeps you pushing hard&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;daily_spark&lt;/code&gt;: flat +10 XP on your first session of the day&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;quest_bonus&lt;/code&gt;: bonus XP from any quests completed this session&lt;/li&gt;
&lt;li&gt;Combined multiplier cap: 3.0× — no runaway math&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;25-Quest System:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;13 &lt;strong&gt;weekly quests&lt;/strong&gt; rotate every Monday: Ship It, Deep Work, Consistency Check, Stack Master, Challenge Accepted, Bug Hunter, Early Bird, Polyglot Week, and more&lt;/li&gt;
&lt;li&gt;12 &lt;strong&gt;permanent milestone quests&lt;/strong&gt;: Century Club, Perfectionist, Streak Legend, Tech Specialist, Versatile, and more&lt;/li&gt;
&lt;li&gt;Quest completion writes to the Quests DB and adds XP to the current session's total&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;30 Achievement Badges&lt;/strong&gt; across three groups — from First Flame (session 1) through Diamond Coder (30-day streak), Deep Diver (three Difficulty-5 sessions in 7 days), Full Stack (frontend + backend in one session), and Achievement Hunter (15+ badges earned).&lt;/p&gt;




&lt;h2&gt;
  
  
  Show Us the Code
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/puginator/devlog" rel="noopener noreferrer"&gt;github.com/puginator/devlog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The distributable config lives in &lt;code&gt;claude-config/&lt;/code&gt;. Here's what makes the system tick:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;claude-config/CLAUDE.md&lt;/code&gt; — The Agent Identity
&lt;/h3&gt;

&lt;p&gt;This file ships the XP formula, difficulty rubric, level thresholds, and all 30 badge definitions into Claude's context on every session. The badge definitions are the most interesting part — they reference in-memory values computed earlier in the same session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Badge Definitions&lt;/span&gt;
Badge checks use post-Step-8 streak value, Total Sessions = Profile Total Sessions + 1,
and provisional Total XP.

| Label | Condition |
|---|---|
| Multiplier | Session where streak_mult ≥ 1.5 AND diff_run_mult = 1.25 AND daily_spark was applied |
| Deep Diver | 3+ sessions with Difficulty = 5 in any rolling 7-day window |
| Full Stack | Session Stack contains ≥ 1 frontend AND ≥ 1 backend technology |
| Achievement Hunter | 15+ badges in Profile Badges Earned |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hard constraints section is what makes the system reliable across sessions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Hard Constraints&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Never hallucinate Notion properties — stop and report errors exactly
&lt;span class="p"&gt;-&lt;/span&gt; Never log empty sessions (no meaningful changes = decline and explain)
&lt;span class="p"&gt;-&lt;/span&gt; Badge checks are idempotent — compare against Badges Earned in Profile before announcing
&lt;span class="p"&gt;-&lt;/span&gt; Quest evaluation is idempotent — check Completed On before awarding quest XP; if set, skip
&lt;span class="p"&gt;-&lt;/span&gt; Stack always written as an array of strings — never a comma-separated string
&lt;span class="p"&gt;-&lt;/span&gt; Difficulty run query always executes before Step 6 to read the previous session only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;claude-config/commands/pulse-check.md&lt;/code&gt; — The Core Workflow
&lt;/h3&gt;

&lt;p&gt;11 steps executed in sequence. A few highlights:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1b — Duplicate check (prevents double-logging the same commit):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;If the commit hash is NOT "uncommitted": search Master Dev Log for an existing row
where Commit Hash matches this hash. If found: stop and say "Already logged commit
[hash] — make a new commit before running Pulse Check again!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4b — XP multiplier computation (pure in-memory, no Notion reads):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;streak_mult:
&lt;span class="p"&gt;-&lt;/span&gt; 7–29 days → 1.5
&lt;span class="p"&gt;-&lt;/span&gt; 30+ days → 2.0
&lt;span class="p"&gt;-&lt;/span&gt; Otherwise → 1.0

diff_run_mult:
Query most recent Master Dev Log row (sort Date descending, limit 1). Read Difficulty.
&lt;span class="p"&gt;-&lt;/span&gt; If previous Difficulty ≥ 4 AND current Difficulty ≥ 4 → 1.25
&lt;span class="p"&gt;-&lt;/span&gt; Otherwise → 1.0

combined_mult = min(streak_mult × diff_run_mult, 3.0)
daily_spark = +10 XP if Last Active Date ≠ today
provisional_xp = floor((Difficulty × 20) × combined_mult) + daily_spark_xp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 9b — Quest evaluation (runs after the session row is written):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each active quest has a specific condition evaluated against the session and Master Dev Log:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ship It (50 XP)&lt;/code&gt;: 3+ sessions logged this ISO week&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Deep Work (50 XP)&lt;/code&gt;: current session Difficulty = 5&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Challenge Accepted (50 XP)&lt;/code&gt;: 2+ sessions this week at Difficulty ≥ 4&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Bug Hunter (50 XP)&lt;/code&gt;: 2+ sessions this week where Commit Message contains "fix" or "bug"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Consistency Check (50 XP)&lt;/code&gt;: sessions logged on 3+ different days this week&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Completed quests update in the Quests DB, add to &lt;code&gt;quest_bonus&lt;/code&gt;, and the session row's &lt;code&gt;XP Earned&lt;/code&gt; is patched with the final total.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6 — Automatic V1→V2 schema migration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Before writing the row, verify Master Dev Log has the &lt;span class="sb"&gt;`XP Earned`&lt;/span&gt; (Number) and
&lt;span class="sb"&gt;`Commit Message`&lt;/span&gt; (Rich Text) properties. If either is missing, add it using
notion_update_database before proceeding.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero manual Notion work to upgrade. DevPulse detects missing columns and adds them on the first V2 run.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;claude-config/commands/weekly-recap.md&lt;/code&gt; — The Recap Generator
&lt;/h3&gt;

&lt;p&gt;The weekly recap queries 7 days of Master Dev Log rows and writes a Notion page. The Growth Narrative step is where it gets interesting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Step 6 — Growth Narrative&lt;/span&gt;
Write a 3–4 sentence analysis of the week. Must reference actual data (most-used stack,
difficulty trend, project focus, streak status). Must include one specific pattern
observation (e.g. "Backend-heavy week — 3 of 5 sessions touched the database layer").
Must end with a forward-looking callout for next week.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude isn't filling in a template — it's reading your actual session data, identifying the pattern, and writing it back as analysis.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Used Notion MCP
&lt;/h2&gt;

&lt;p&gt;Notion MCP is the entire backend of DevPulse. Every piece of state lives in Notion. Claude reads and writes through &lt;code&gt;@notionhq/notion-mcp-server&lt;/code&gt; — there's no local database, no config file, no server of any kind.&lt;/p&gt;

&lt;p&gt;Here's every MCP operation the system uses:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;notion_search&lt;/code&gt; — Database discovery
&lt;/h3&gt;

&lt;p&gt;Every workflow starts by finding its databases by name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;notion_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Master Dev Log&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="nf"&gt;notion_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DevPulse Profile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;XP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;streak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;badges&lt;/span&gt;
&lt;span class="nf"&gt;notion_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DevPulse Quests&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="n"&gt;quests&lt;/span&gt;
&lt;span class="nf"&gt;notion_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DevPulse Recaps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;weekly&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;monthly&lt;/span&gt; &lt;span class="n"&gt;summaries&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what makes DevPulse portable. The databases can live anywhere in your Notion workspace.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;notion_query_database&lt;/code&gt; — Precise filtered reads
&lt;/h3&gt;

&lt;p&gt;The quest system and badge checks require querying Master Dev Log with specific filters:&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="c1"&gt;# Sessions this ISO week (quest evaluation)&lt;/span&gt;
&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;Date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;on_or_after&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-03-16"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;on_or_before&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-03-22"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Previous session only (diff_run_mult)&lt;/span&gt;
&lt;span class="na"&gt;sorts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[{&lt;/span&gt; &lt;span class="nv"&gt;property&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Date"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;direction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;descending"&lt;/span&gt; &lt;span class="pi"&gt;}]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;page_size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# All Difficulty-5 sessions (Deep Diver badge, Hardcore badge)&lt;/span&gt;
&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;Difficulty&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;equals&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;5&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Active quests only&lt;/span&gt;
&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;Status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;equals&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Active"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;notion_create_page&lt;/code&gt; — Writing session data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;notion_create_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;database_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;master_dev_log_id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Session Title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Async Queue System for Ad Insertion Engine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Project&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ad-engine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TypeScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Node.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Redis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="nx"&gt;always&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Difficulty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;XP Earned&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;247&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-03-19&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Commit Hash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a3f9b2c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Commit Message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;feat: implement async ad queue with retry logic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Stack&lt;/code&gt; is always written as an array of strings — a hard constraint in &lt;code&gt;CLAUDE.md&lt;/code&gt; because early versions wrote &lt;code&gt;"TypeScript, React"&lt;/code&gt; as a single value, which broke the tech frequency aggregation in weekly recaps.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;notion_update_page&lt;/code&gt; — State management
&lt;/h3&gt;

&lt;p&gt;After writing the session, DevPulse updates the Profile and patches the session row if quests completed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Profile&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt;
&lt;span class="nf"&gt;notion_update_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile_row_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Current Streak&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Total XP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1847&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Current Level&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Staff Engineer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Badges Earned&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First Flame&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bug Slayer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Week Warrior&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Challenge Accepted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Last Active Date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-03-19&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Session&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="nx"&gt;patched&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;final&lt;/span&gt; &lt;span class="nx"&gt;XP&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="nx"&gt;quest&lt;/span&gt; &lt;span class="nx"&gt;bonuses&lt;/span&gt; &lt;span class="nx"&gt;resolved&lt;/span&gt;
&lt;span class="nf"&gt;notion_update_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session_row_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;XP Earned&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;247&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;  &lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="nx"&gt;was&lt;/span&gt; &lt;span class="mi"&gt;187&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt; &lt;span class="nx"&gt;quest&lt;/span&gt; &lt;span class="nx"&gt;bonus&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Quest&lt;/span&gt; &lt;span class="nx"&gt;marked&lt;/span&gt; &lt;span class="nx"&gt;complete&lt;/span&gt;
&lt;span class="nf"&gt;notion_update_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quest_row_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Completed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Completed On&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-03-19&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;notion_update_database&lt;/code&gt; — Schema migration
&lt;/h3&gt;

&lt;p&gt;V1→V2 upgrade adds missing columns automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;notion_update_database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;master_dev_log_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;XP Earned&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Commit Message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rich_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Runs once, on the first V2 &lt;code&gt;/pulse-check&lt;/code&gt;, only if the columns don't exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auto-creating databases on first run
&lt;/h3&gt;

&lt;p&gt;If DevPulse Profile or DevPulse Quests don't exist, Claude creates them with the full schema and seeds all 25 quests in a single batch — 12 milestone quests as Active rows, plus 3 weekly quests timed to the current week's deadline.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Notion MCP Was the Right Choice
&lt;/h3&gt;

&lt;p&gt;DevPulse works because Notion is actually a real relational database, not just a note-taking app. Filtering by date, sorting by difficulty, updating specific properties, running schema migrations — all the things you'd normally need a backend for are just Notion API calls.&lt;/p&gt;

&lt;p&gt;@notionhq/notion-mcp-server gives Claude direct access to every Notion operation from inside the conversation context. No server needed. The entire DevPulse backend is: Claude + a markdown config file + MCP.&lt;/p&gt;

&lt;p&gt;The MCP interface is the key piece. Without it, I'd need a server to broker requests between Claude and the Notion API. With &lt;code&gt;@notionhq/notion-mcp-server&lt;/code&gt;, Claude has direct access to every Notion operation from inside the conversation context. The entire DevPulse backend is: Claude + a markdown config file + MCP. That's it.&lt;/p&gt;




&lt;p&gt;DevPulse is open source and works for anyone with Claude Code. Clone the repo, run &lt;code&gt;setup.sh&lt;/code&gt;, and your first &lt;code&gt;/pulse-check&lt;/code&gt; sets everything up automatically — including writing your first entry to Notion and starting your streak at day 1.&lt;/p&gt;

&lt;p&gt;If you're just starting to code, that first entry is going to mean more than you think it will six months from now.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Building SoloQuest: Letting Gemini Be the DM, and Code Be the Referee</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Mon, 02 Mar 2026 05:08:09 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/building-soloquest-letting-gemini-be-the-dm-and-code-be-the-referee-3e89</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/building-soloquest-letting-gemini-be-the-dm-and-code-be-the-referee-3e89</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mlh-built-with-google-gemini-02-25-26"&gt;Built with Google Gemini: Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built with Google Gemini
&lt;/h2&gt;

&lt;p&gt;SoloQuest started with a question that felt a little absurd and a little irresistible:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Could I build a solo D&amp;amp;D 5e campaign where an AI acts as the Dungeon Master, and have it actually feel coherent for more than a few turns?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At first, this was just a prompt experiment in Google AI Studio. I wanted to see whether Gemini could stay in character as a rules-aware DM over a long conversation. The early results were exciting. Gemini was great at scene-setting, roleplay, and making even simple encounters feel dramatic.&lt;/p&gt;

&lt;p&gt;Then the cracks started to show.&lt;/p&gt;

&lt;p&gt;A goblin would attack twice because initiative state drifted. A defeated enemy would still be described as active. A spell slot would get consumed in the narration but not in the actual game state. Death saves sounded correct and still ended up inconsistent.&lt;/p&gt;

&lt;p&gt;That was the turning point. I realized I was trying to use Gemini for two jobs at once:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;storytelling&lt;/li&gt;
&lt;li&gt;stateful rules execution&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It was excellent at the first and unreliable at the second.&lt;/p&gt;

&lt;p&gt;That insight became the architecture for SoloQuest.&lt;/p&gt;

&lt;p&gt;Today, SoloQuest is a full-stack Next.js app with Firebase Auth and Firestore, Stripe subscriptions, Google Text-to-Speech for narration, and Gemini powering the core game experience. The model handles narration, roleplay, encounter flavor, NPC dialogue, and player choice framing. My code handles the deterministic layer: combat state, initiative, HP math, spell slots, inventory, conditions, progression, and persistence.&lt;/p&gt;

&lt;p&gt;The core loop works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The player enters an action&lt;/li&gt;
&lt;li&gt;The app sends Gemini the current campaign context, including character state, combat state, inventory, quest context, and recent session history&lt;/li&gt;
&lt;li&gt;Gemini returns both narrative text and a structured &lt;code&gt;MECHANICS&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;A deterministic rules engine parses that block and applies the actual state transitions&lt;/li&gt;
&lt;li&gt;Everything is saved back to Firestore so the campaign can continue across sessions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Gemini plays the DM. My code plays the referee.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That division of labor turned a fun prototype into a real product.&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.amazonaws.com%2Fuploads%2Farticles%2Fc78fgoymsan75hod1yu0.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fc78fgoymsan75hod1yu0.webp" alt="Screenshot of the game" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;You can try SoloQuest at &lt;a href="https://thesoloquest.com" rel="noopener noreferrer"&gt;thesoloquest.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;h3&gt;
  
  
  The Most Important Design Decision Was Deciding What the AI Was Allowed to Do
&lt;/h3&gt;

&lt;p&gt;The biggest lesson from this project had nothing to do with clever prompts. It was about system boundaries.&lt;/p&gt;

&lt;p&gt;Early on, I kept trying to fix mechanical inconsistency with better instructions. I added more rules to the system prompt, more formatting requirements, more reminders about initiative order, death saves, conditions, and spell slots. It helped a little, but not enough. The problem was not that Gemini was failing to read my instructions. The problem was that I was assigning deterministic responsibilities to a probabilistic system.&lt;/p&gt;

&lt;p&gt;Once I accepted that, progress became much faster.&lt;/p&gt;

&lt;p&gt;Over eight phases of development, I moved game mechanics out of Gemini and into a rules engine. Gemini still decides how the world sounds and feels. The engine decides what actually happens.&lt;/p&gt;

&lt;p&gt;That changed everything.&lt;/p&gt;

&lt;p&gt;Here are a few examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initiative and turn order&lt;/strong&gt; are fully engine-controlled. My code rolls initiative, sorts combatants, advances turns, and enforces who can act.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attack resolution&lt;/strong&gt; uses real AC and stat data. Gemini can narrate a hit, but if the math says it missed, the engine wins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditions&lt;/strong&gt; like stunned, grappled, and paralyzed are stored as structured state with start-of-turn and end-of-turn hooks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spells&lt;/strong&gt; are resolved by deterministic handlers based on spell category, such as attack roll, saving throw, auto-hit, or area effect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reactions&lt;/strong&gt; like Shield, Uncanny Dodge, and Opportunity Attacks are surfaced as interactive prompts instead of left to narration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encounter generation&lt;/strong&gt; is constrained by SRD-based balance rules so the model has creative freedom without producing absurd difficulty spikes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key mental model became:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini should generate intent and drama. The engine should own truth.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That idea ended up being useful beyond games. It feels like a general rule for building with LLMs. If the model is responsible for something that must be correct every time, you should seriously consider whether that responsibility belongs in code instead.&lt;/p&gt;

&lt;p&gt;The most valuable non-technical skill here was learning how to design the handoff between AI output and deterministic systems. That handoff is easy to underestimate, but in a product like this it defines the user experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  Google Gemini Feedback
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Worked Really Well
&lt;/h3&gt;

&lt;p&gt;Gemini is genuinely strong at long-form narrative interaction. It does a good job maintaining tone, pacing, and scene continuity across many turns, which matters a lot in a solo RPG where the model is effectively carrying the voice of the world.&lt;/p&gt;

&lt;p&gt;It was also strong enough at structured output to support a hybrid architecture. I instructed it to always include a &lt;code&gt;MECHANICS&lt;/code&gt; block alongside the narrative, and that gave me a consistent enough interface to build a parser and rules engine around.&lt;/p&gt;

&lt;p&gt;A typical response pattern looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NARRATIVE:
The goblin lunges from behind the crates, dagger flashing in the torchlight.

MECHANICS:
ACTION_TYPE: ATTACK
SOURCE: goblin_1
TARGET: player
ATTACK_TYPE: dagger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is that Gemini is not trusted to finalize the outcome. It declares intent. The engine resolves whether the attack hits, how much damage is applied, whether a reaction is available, and what the updated combat state becomes.&lt;/p&gt;

&lt;p&gt;I also liked working with the &lt;code&gt;@google/genai&lt;/code&gt; SDK. It felt straightforward to integrate, and one design choice that paid off early was versioning my system instruction. I keep a &lt;code&gt;SYSTEM_INSTRUCTION_VERSION&lt;/code&gt; constant so I can evolve the DM prompt over time without corrupting older save files or creating mismatches across campaigns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where I Hit Friction
&lt;/h3&gt;

&lt;p&gt;The biggest friction point was long-context consistency.&lt;/p&gt;

&lt;p&gt;As campaigns grew, Gemini would sometimes drift from earlier constraints. It might quietly invent a mechanic, forget a restriction, or phrase a response in a way that implied a state change that never actually happened. This forced me to constantly ask whether a bug belonged to prompt design, parser design, or the underlying architecture.&lt;/p&gt;

&lt;p&gt;The second major friction point was output normalization. Even when Gemini followed the general structure, the exact formatting could vary. I ended up building a fairly defensive parser that handles misplaced directives, missing separators, whitespace variation, partial formatting failures, and narrative text leaking into the mechanics section.&lt;/p&gt;

&lt;p&gt;That parser exists because the model was good enough to be useful, but not rigid enough to be treated like a strict protocol.&lt;/p&gt;

&lt;p&gt;I also felt the absence of a more native function-style interface for state mutations in this workflow. I effectively created a domain-specific command layer for the model to speak through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HP_CHANGE: -12
CONDITION_ADD: poisoned
SPELL_SLOT_USED: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That worked, but it shifted complexity into my application. A more direct way to return strongly structured actions would have simplified a lot of infrastructure.&lt;/p&gt;

&lt;p&gt;The messiest failure mode was hallucinated state. In early versions, Gemini would occasionally introduce enemies I had never spawned, add items that were never earned, or award XP for events that had not actually occurred. To contain that, I added a validation layer that checks model responses before any game state is mutated. If validation fails, the app sends a repair prompt asking Gemini to correct the output.&lt;/p&gt;

&lt;p&gt;That helped reliability, but it also introduced latency because a bad response can require an additional model call.&lt;/p&gt;

&lt;p&gt;In the end, Gemini got much better as soon as I narrowed its job description. The more precise I was about what belonged to the model and what belonged to the engine, the better the overall system behaved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where I'm Headed Next
&lt;/h2&gt;

&lt;p&gt;The engine is now through eight phases of rules implementation. The remaining work is less about core feasibility and more about completeness and production hardening: item economy, attunement, ammunition tracking, encumbrance, error dashboards, combat-friction telemetry, feature flags, and migration tooling for older campaigns.&lt;/p&gt;

&lt;p&gt;What is interesting is that as the engine becomes more capable, the prompt becomes simpler.&lt;/p&gt;

&lt;p&gt;Rules that Gemini used to carry in prompt instructions are now enforced directly in code. That means I can remove prompt complexity instead of adding to it. The system gets more reliable while the model's role becomes more focused.&lt;/p&gt;

&lt;p&gt;That is where I think this architecture is heading:&lt;/p&gt;

&lt;p&gt;Gemini handles prose, pacing, roleplay, and choice design. The engine handles rules, state, and truth.&lt;/p&gt;

&lt;p&gt;That separation is what made SoloQuest viable, and it is the main thing I would tell anyone building with Gemini from day one:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use the model for what it is uniquely good at. Protect that space. Move everything deterministic out of it as quickly as you can.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;You can try SoloQuest at &lt;a href="https://thesoloquest.com" rel="noopener noreferrer"&gt;thesoloquest.com&lt;/a&gt;. Your first 50 turns are free. If you are building with Gemini or experimenting with AI-driven game systems, I would love to compare notes in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>geminireflections</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Pinned Brews - A social coffee community</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Mon, 02 Mar 2026 04:21:06 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/pinned-brews-a-social-coffee-community-2m5d</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/pinned-brews-a-social-coffee-community-2m5d</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/weekend-2026-02-28"&gt;DEV Weekend Challenge: Community&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Community
&lt;/h2&gt;

&lt;p&gt;I spent 12 years in the specialty coffee world before pivoting into web development in 2020. One thing I always wished existed was a simple place to see what other people were actually brewing, enjoying, and recommending.&lt;/p&gt;

&lt;p&gt;There are plenty of places to buy coffee, but not many places that make it easy to discover new coffees and roasters through other people’s real brew logs and tasting notes. I built Pinned Brews for that kind of coffee community: people who love trying new roasters, comparing brew methods, and sharing what’s in their cup.&lt;/p&gt;

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

&lt;p&gt;I built &lt;strong&gt;Pinned Brews&lt;/strong&gt;, a social coffee logging app where people can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;post the coffees they’re drinking&lt;/li&gt;
&lt;li&gt;log brew methods, ratios, and tasting notes&lt;/li&gt;
&lt;li&gt;discover new roasters through a public feed&lt;/li&gt;
&lt;li&gt;build profiles around their coffee habits&lt;/li&gt;
&lt;li&gt;unlock achievements for exploring and posting&lt;/li&gt;
&lt;li&gt;get AI-powered brew suggestions for future tweaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was to keep the app simple and approachable while still making it fun to explore what the wider coffee community is brewing.&lt;/p&gt;

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

&lt;p&gt;Give it a try here: &lt;a href="https://pinned-brews.vercel.app/" rel="noopener noreferrer"&gt;Pinned Brews&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Repo: &lt;a href="https://github.com/puginator/pinned-brews" rel="noopener noreferrer"&gt;github.com/puginator/pinned-brews&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I built Pinned Brews with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; for the app frontend and routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase&lt;/strong&gt; for auth and database storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; for deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini&lt;/strong&gt; for AI brew suggestions&lt;/li&gt;
&lt;li&gt;custom SVG brew method icons for a more coffee-specific UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also used AI tools during the build process to quickly explore early UI ideas, generate some custom brew graphics, and help organize seed data from roasters and coffees listed on drinktrade.com.&lt;/p&gt;

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

&lt;p&gt;This project was a fun way to combine two parts of my background: specialty coffee and web development. The biggest challenge was keeping the app lightweight and fun while still making it feel like a real community product instead of just a personal brew tracker.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;p&gt;If I keep building it out, I’d love to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;comments and discussions on brews&lt;/li&gt;
&lt;li&gt;following favorite brewers or roasters&lt;/li&gt;
&lt;li&gt;richer coffee search and filtering&lt;/li&gt;
&lt;li&gt;more personalized discovery features&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Prompt Architecture for a Reliable AI Dungeon Master</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Fri, 27 Feb 2026 05:45:30 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/prompt-architecture-for-a-reliable-ai-dungeon-master-d99</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/prompt-architecture-for-a-reliable-ai-dungeon-master-d99</guid>
      <description>&lt;p&gt;&lt;em&gt;How I structured prompts to make an LLM behave like a consistent, rule-following D&amp;amp;D 5e GM and actually stay that way across long sessions.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Building an AI Dungeon Master sounds straightforward until you actually try it.&lt;/p&gt;

&lt;p&gt;Left to its own devices, an LLM will happily let a level-1 fighter dual-wield longswords, cast spells they never learned, and narrate a killing blow before the player has rolled a single die. Fun the first time. Maddening as a recurring loop.&lt;/p&gt;

&lt;p&gt;The core challenge isn't creativity LLMs are genuinely great at that. The challenge is &lt;strong&gt;consistency&lt;/strong&gt;. D&amp;amp;D 5e has hundreds of interlocking rules, and a solo player with no human GM to correct mistakes will notice &lt;em&gt;fast&lt;/em&gt; when the AI forgets that Warlocks recharge spell slots on a short rest, or that a Bard can't swap their Known Spells mid-dungeon. Get caught bending the rules once, and the player trusts nothing.&lt;/p&gt;

&lt;p&gt;Here's how I tackled it in &lt;a href="https://thesoloquest.com" rel="noopener noreferrer"&gt;SoloQuest&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1: The System Prompt as a Rules Contract
&lt;/h2&gt;

&lt;p&gt;The foundation is a dense, versioned system instruction (currently on v9) that functions less like a creative brief and more like a &lt;strong&gt;contract the model has to sign before every session&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It covers things like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inventory and resource tracking.&lt;/strong&gt; The AI is told explicitly what it can and cannot offer based on the current character state. Confiscated items are off-limits. When a consumable gets used, the model emits a machine-readable tag (&lt;code&gt;ITEM_USED: Item Name&lt;/code&gt;) that the game parser watches for. Same with ability charges. This isn't vague guidance, it's a protocol.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spell management by caster type.&lt;/strong&gt; Rather than one generic spell rule, the prompt distinguishes three different systems: prepared casters (Cleric, Druid, Paladin), known casters (Bard, Sorcerer, Warlock), and spellbook casters (Wizard). Each one has different rules for what they can cast and when their slots come back. Warlocks even get a dedicated callout, because "Warlock slots recharge on short rest, not long rest" is one of the most common AI failure modes I ran into early on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rolls are mandatory before outcomes.&lt;/strong&gt; This one is bolded in the prompt. The model gets shown the &lt;em&gt;wrong&lt;/em&gt; pattern ("Your sword strikes true, dealing 8 damage!") and the &lt;em&gt;correct&lt;/em&gt; one: request the roll, wait, then narrate after. Without this, the AI just collapses into a choose-your-own-adventure book where the dice are decoration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encounter balance guardrails.&lt;/strong&gt; At levels 1-3, solo encounters have hard HP caps baked into the prompt (level 1 enemies: max 7 HP, no multiattack). A single bad roll at low level with no party to pick you up is a run-ender, so I encoded the balance logic directly rather than hoping the model had good instincts about what's "survivable."&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 2: Injecting the Rules Right When They're Needed
&lt;/h2&gt;

&lt;p&gt;The system prompt handles general behavior, but specific mechanics need to be fresh in context &lt;em&gt;exactly&lt;/em&gt; when they matter.&lt;/p&gt;

&lt;p&gt;Every turn, I run the player's input through a lightweight keyword extractor that picks up signals: Are there active enemies? Is the player low on HP? What class are they? What verb did they use, "attack," "sneak," "cast"?&lt;/p&gt;

&lt;p&gt;From those signals, a scoring function pulls the top 3 most relevant rules from a structured SRD database and drops them directly into the user prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;RELEVANT D&amp;amp;D 5E RULES (Follow these strictly):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sneak Attack: Requires a finesse or ranged weapon, plus advantage or an ally adjacent to the target...&lt;/li&gt;
&lt;li&gt;Two-Weapon Fighting: The off-hand attack uses a bonus action and does not add your modifier to damage...&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means the model doesn't have to &lt;em&gt;recall&lt;/em&gt; Sneak Attack from training data. The rule is just sitting right there in the prompt when the Rogue tries to use it. Scoring is weighted (exact tag match scores highest, loose content match scores lowest), and irrelevant rules get filtered out so they don't clutter the context window.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 3: Game State as the Source of Truth
&lt;/h2&gt;

&lt;p&gt;The most brittle moment in a long session is continuity. After 30 turns, does the model remember the player is concentrating on &lt;em&gt;Hold Person&lt;/em&gt;? That the goblin lieutenant &lt;em&gt;fled&lt;/em&gt; rather than died? That the fighter is at 3 of 12 HP?&lt;/p&gt;

&lt;p&gt;To handle this, I serialize the &lt;strong&gt;entire engine state&lt;/strong&gt; into every prompt turn. The AI always receives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Combat state:&lt;/strong&gt; initiative order, whose turn it is, each enemy's distance and line of sight, cover values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exploration state:&lt;/strong&gt; travel pace, light level, time elapsed, last passive perception result&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Death save tracker:&lt;/strong&gt; active or not, current success/failure counts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active effects:&lt;/strong&gt; conditions with round durations, poisons with their DCs, disease stage progression&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The prompt declares these trackers as &lt;em&gt;authoritative&lt;/em&gt;. The AI cannot narrate hitting an enemy behind full cover, can't apply damage to a character with immunity, can't start concentrating on a second spell without dropping the first. The state in context is the source of truth, not whatever the model thinks it remembers.&lt;/p&gt;

&lt;p&gt;One more detail worth calling out: the machine-readable combat trace from the &lt;em&gt;previous&lt;/em&gt; turn also gets passed in. This gives the model a clear record of what mechanics were actually applied last round, which prevents a frustrating drift pattern where the model re-narrates a hit that was actually a miss.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 4: Enforced Response Structure
&lt;/h2&gt;

&lt;p&gt;Parsing AI output reliably means removing all ambiguity from the format. Every turn, the model is required to return four sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;[NARRATIVE]&lt;/strong&gt; — the story beat, written however it likes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[MECHANICS]&lt;/strong&gt; — machine-readable tags only (&lt;code&gt;HP_CHANGE:-8&lt;/code&gt;, &lt;code&gt;ENEMY_HP: Goblin Scout, 4&lt;/code&gt;, &lt;code&gt;ROLL:1d20+DEX for Stealth&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[SUGGESTIONS]&lt;/strong&gt; — player options, each tagged as requiring a roll or not&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[CHRONICLE]&lt;/strong&gt; — a one-line campaign log entry, only on significant beats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The parser maps the mechanics tags directly to state transitions in the game engine. &lt;code&gt;HP_CHANGE&lt;/code&gt;, &lt;code&gt;ENEMY_SPAWN&lt;/code&gt;, &lt;code&gt;ITEM_GAINED&lt;/code&gt;, &lt;code&gt;SPELL_SLOT_USED&lt;/code&gt;, &lt;code&gt;CONCENTRATION&lt;/code&gt; all feed deterministic updates. The AI's prose can be whatever it wants, but the mechanics section has to be machine-readable.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;roll:true/false&lt;/code&gt; flag on each suggestion is checked by the client before an action gets sent. If a suggestion requires a roll and the player hasn't provided one, the UI stops and prompts for it. The AI can't skip the dice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing: No Unit Tests, Just Instrumented Playtesting
&lt;/h2&gt;

&lt;p&gt;There's no test suite for DM behavior. A spec can tell you if a function returns the right boolean, but it can't tell you whether the goblin acted like a goblin.&lt;/p&gt;

&lt;p&gt;Instead, I leaned on a few practices:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debug logging at parse time.&lt;/strong&gt; Every injected SRD rule gets logged. Every mechanic event gets logged. This is how I caught the model emitting &lt;code&gt;ITEM_GAINED: Health Potion x1&lt;/code&gt; (with a quantity suffix the parser didn't expect) and traced it back to a missing naming constraint in the prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version bumping as change control.&lt;/strong&gt; The system instruction version constant forces a cache miss on character caches whenever the prompt changes. What felt like a minor clarification sometimes produced drastically different combat behavior. Treating each meaningful edit as a version was the only way to reason about what actually changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure pattern cataloguing.&lt;/strong&gt; When the AI broke a rule, I wrote it down, not as a bug ticket, but as a new clause in the system prompt. &lt;em&gt;"Do not narrate level-ups directly, the game system handles this automatically"&lt;/em&gt; is in there because the model confidently told players "You feel a surge of power, you are now level 3!" on three separate playtests. Every clause traces back to a real failure.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;p&gt;The biggest tension is prompt size vs. model attention. At v9, the system instruction is around 350 lines before any per-turn context is added. Long-context models handle the length fine, but rules buried in the middle of a dense block can get overshadowed by recency effects from the conversation history.&lt;/p&gt;

&lt;p&gt;Looking back, I'd front-load the most commonly violated rules (roll-before-outcome, spell prep rules) closer to the top, and probably split the narrative craft guidance into a separate injection that only appears during non-combat turns. There's no reason to spend context budget on "pacing and encounter variety" guidance while the player is mid-fight.&lt;/p&gt;

&lt;p&gt;The SRD injection approach scales really well though. Adding a new mechanic like attunement, exhaustion, or diseases just means writing one structured rule object with tags and dropping it into the right category file. The scoring handles the rest.&lt;/p&gt;




&lt;p&gt;Getting an LLM to follow structured rules reliably is harder than it looks. The model will do what the prompt describes, but only if the description is precise enough, and precise enough turns out to be a moving target. The real work is translating a rulebook written for human interpretation into something that survives a 50-turn campaign without drifting.&lt;/p&gt;

&lt;p&gt;That gap between "the rules" and "what the model actually does" is where most of the engineering lives.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Building something AI-powered and running into consistency issues? I'd love to hear how you're handling it in the comments.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>I'm Solo-Devving an AI D&amp;D Game — and Now I'm Building in Public</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Tue, 17 Feb 2026 00:51:09 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/im-solo-devving-an-ai-dd-game-and-now-im-building-in-public-kcd</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/im-solo-devving-an-ai-dd-game-and-now-im-building-in-public-kcd</guid>
      <description>&lt;p&gt;I've been quietly building &lt;a href="https://thesoloquest.com" rel="noopener noreferrer"&gt;The SoloQuest&lt;/a&gt; for a while now, and I think it's time to start talking about it.&lt;/p&gt;

&lt;p&gt;The SoloQuest is an AI-powered solo D&amp;amp;D 5e experience — basically a personal AI Dungeon Master that lets you create a character, pick a scenario, and play through a fully narrated adventure with real ability checks, combat mechanics, and death saves. No scheduling, no party coordination, just you and the dice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Started Building This
&lt;/h2&gt;

&lt;p&gt;Like a lot of D&amp;amp;D fans, I love the game but struggle to get a group together consistently. I wanted something that captured the &lt;em&gt;feel&lt;/em&gt; of sitting at a table — the narrative tension, the mechanical crunch, the "oh no I rolled a 3" moments — but that I could pick up anytime on any device. When I went to the web I found Old Greg's Tavern and thought this is so cool, but I wish I could change a few things.&lt;/p&gt;

&lt;p&gt;So I started building it myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Been Fun
&lt;/h2&gt;

&lt;p&gt;A few things have made this project genuinely enjoyable to work on:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The AI side is endlessly interesting.&lt;/strong&gt; Getting an AI to act as a competent DM — one that tracks state, enforces rules, creates compelling NPCs, and doesn't just hand you the win — is a fascinating problem. Every iteration teaches me something new about prompt design and how to keep narratives coherent over long sessions. Also its been great practice adding agents and different skills to my workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Character creation was a blast to design.&lt;/strong&gt; There are 40+ archetypes spanning all the D&amp;amp;D 5e races and classes, each with unique backstories and flavor. Building out that system and seeing characters like a Tiefling Shadowbound Arcanist or a Halfling Quickstep Trickster come to life was incredibly rewarding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It actually works.&lt;/strong&gt; There's something special about playing your own product and getting lost in it. I've caught myself doing "just one more turn" testing sessions that turned into actual adventures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm Building in Public Now
&lt;/h2&gt;

&lt;p&gt;Here's the honest part: solo development is isolating. You can grind away for months and nobody knows or cares. The momentum comes entirely from within, and some days that tank runs dry.&lt;/p&gt;

&lt;p&gt;I've decided to start posting about the process here because I think accountability and community are the missing pieces. I want to share the wins, the weird bugs, the design decisions, the things I've learned about AI, game design, and shipping a product as one person.&lt;/p&gt;

&lt;p&gt;If you're into any combination of D&amp;amp;D, AI, indie game dev, or just the solo dev grind, I'd love for you to follow along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check It Out
&lt;/h2&gt;

&lt;p&gt;You can try it at &lt;a href="https://thesoloquest.com" rel="noopener noreferrer"&gt;thesoloquest.com&lt;/a&gt; — your first 50 turns are free. I also have a &lt;a href="https://discord.gg/BA8wYbzY2m" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; if you want to connect directly.&lt;/p&gt;

&lt;p&gt;More posts coming soon, hopefully. Next up I'll probably dig into some of the technical challenges of making AI follow D&amp;amp;D rules without going off the rails. 🎲&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow me here on dev.to to keep up with the journey. And if you've got questions about the game or the stack, drop them in the comments — I'm an open book.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Building a D&amp;D inspired Dungeon Crawler with GitHub Copilot CLI</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Fri, 06 Feb 2026 06:55:54 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/building-a-dd-inspired-dungeon-crawler-with-github-copilot-cli-9d8</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/building-a-dd-inspired-dungeon-crawler-with-github-copilot-cli-9d8</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I set out to build a D&amp;amp;D dungeon crawler web game using TypeScript and React—a unique twist that uses Unix-style file system commands (&lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;chmod&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;) as gameplay mechanics in an effort to help me remember the commands. &lt;/p&gt;

&lt;p&gt;With GitHub Copilot CLI, I transformed this from a scattered idea into a fully-tested, deployed web application in just a few hours.&lt;/p&gt;

&lt;p&gt;TLDR; CLI Dungeon Crawler: Try it &lt;a href="https://cli-dnd.vercel.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  The Approach
&lt;/h2&gt;

&lt;p&gt;Rather than building everything myself, I used &lt;strong&gt;Copilot CLI to plan out what exactly I wanted to build&lt;/strong&gt;, then make smart architectural decisions, and validate everything with tests. Here's how:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Explore&lt;/strong&gt; - Suggest and explore what I want to build&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design&lt;/strong&gt; - Make informed architectural and technical decisions
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build&lt;/strong&gt; - Implement with confidence&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test&lt;/strong&gt; - Validate constantly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy&lt;/strong&gt; - Ship to Vercel&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✨ Deployed Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Random Dungeon Generation&lt;/strong&gt; (4-13 rooms, validated)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Boss System&lt;/strong&gt; (difficulty scales with dungeon size)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Boss Spawn Detection&lt;/strong&gt; (triggers when ready)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Victory System&lt;/strong&gt; (defeat boss to win)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Combat UI&lt;/strong&gt; (TypeScript/React)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expanded Unix-style Commands&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Navigation: &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;pwd&lt;/code&gt;, &lt;code&gt;tree&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Interaction: &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;chmod&lt;/code&gt;, &lt;code&gt;unlock&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;touch&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt;, &lt;code&gt;tail&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Character: &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;inventory&lt;/code&gt;, &lt;code&gt;whoami&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Combat: &lt;code&gt;attack&lt;/code&gt;, &lt;code&gt;defend&lt;/code&gt;, &lt;code&gt;cast&lt;/code&gt;, &lt;code&gt;flee&lt;/code&gt; (with a/d/s/f shortcuts)&lt;/li&gt;
&lt;li&gt;System: &lt;code&gt;help&lt;/code&gt;, &lt;code&gt;history&lt;/code&gt;, &lt;code&gt;man&lt;/code&gt;, &lt;code&gt;echo&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;quit&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Copilot CLI Improved Development
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Fast Architecture Understanding&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of manually reading code, I got precise answers: "How does dungeon generation work?" → immediate exploration results.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Confident Refactoring&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Dynamic boss system required changes to game flow. Tests ran instantly. Zero breaking changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Better Design Decisions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before implementing boss spawn logic, I verified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How room state is tracked&lt;/li&gt;
&lt;li&gt;The game flow architecture&lt;/li&gt;
&lt;li&gt;Best places for integration hooks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Comprehensive Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Created test suite covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Room count constraints&lt;/li&gt;
&lt;li&gt;Boss difficulty scaling&lt;/li&gt;
&lt;li&gt;Victory detection&lt;/li&gt;
&lt;li&gt;State management&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Ready for Production&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Validated, tested code ready for Vercel deployment immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Explore the codebase systematically&lt;/strong&gt; before making changes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Write tests that validate business logic&lt;/strong&gt;, not just happy paths&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Get feedback immediately&lt;/strong&gt; - tests run in seconds&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Deploy with confidence&lt;/strong&gt; - zero test regressions means zero surprises&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Keep the development loop tight&lt;/strong&gt; - explore → build → test → deploy&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;A fun, playable, fully-tested D&amp;amp;D dungeon crawler that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works with random dungeons&lt;/li&gt;
&lt;li&gt;Scales difficulty automatically&lt;/li&gt;
&lt;li&gt;Has smart boss spawn logic&lt;/li&gt;
&lt;li&gt;Provides satisfying victory conditions&lt;/li&gt;
&lt;li&gt;Is well-documented&lt;/li&gt;
&lt;li&gt;Has comprehensive test coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But more importantly: a case study in how GitHub Copilot CLI can transform your development process from linear and error-prone to iterative and confident.&lt;/p&gt;

&lt;h2&gt;
  
  
  Play It Now
&lt;/h2&gt;

&lt;p&gt;The game is deployed and playable. Visit the live application on &lt;a href="https://cli-dnd.vercel.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This works way better on a computer vs phone just FYI&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot CLI really changed my approach to this whole project from start to finish&lt;br&gt;
&lt;strong&gt;What changed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detailed suggestions and creation of a plan&lt;/li&gt;
&lt;li&gt;Step by step implementation of suggested plan&lt;/li&gt;
&lt;li&gt;By breaking it into steps allowed me to test and build piece by piece&lt;/li&gt;
&lt;li&gt;Features were easy to add with its context of the project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All with zero test regressions and complete feature coverage.&lt;/p&gt;

&lt;p&gt;If you're building something, use this workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Explore thoroughly&lt;/li&gt;
&lt;li&gt;Test constantly&lt;/li&gt;
&lt;li&gt;Deploy with confidence&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the power of GitHub Copilot CLI integrated into your development process.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Austin Amento&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Creator of CLI-DND&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;2026&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>Forge your experience Without the Chat: Building Proactive D&amp;D Tools with Algolia</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Thu, 29 Jan 2026 04:39:38 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/forge-your-experience-without-the-chat-building-proactive-dd-tools-with-algolia-5013</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/forge-your-experience-without-the-chat-building-proactive-dd-tools-with-algolia-5013</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/algolia"&gt;Algolia Agent Studio Challenge&lt;/a&gt;: Consumer-Facing Non-Conversational Experiences&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Beyond the Chatbot
&lt;/h2&gt;

&lt;p&gt;Not every intelligent experience needs to be a conversation.&lt;/p&gt;

&lt;p&gt;When you're building a PC, you don't want to &lt;em&gt;chat&lt;/em&gt; about compatibility—you want the system to just know that your AMD motherboard won't work with an Intel CPU. When you're creating a fashion look, you don't want to ask "does this match?"—you want suggestions that already complement your choices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Adventurer's Codex&lt;/strong&gt; applies this philosophy to Dungeons &amp;amp; Dragons. While the Oracle module offers conversational discovery, three other modules demonstrate how contextual data retrieval can proactively assist users within existing workflows—no dialogue required.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three Non-Conversational Experiences
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The Forge: Guided Character Building with Smart Compatibility
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: Building a D&amp;amp;D character requires making interdependent choices. Your race should complement your class. Your subclass should fit your playstyle. But traditional builders just show you lists—they don't tell you what works well together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: The Forge is a step-by-step wizard that uses Algolia's filtering to proactively surface compatible options at each stage.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. DM Mode: Contextual Encounter Suggestions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: Dungeon Masters improvise constantly. A player goes off-script, and suddenly you need a monster. You're writing a scene description and realize you need a trap. Stopping to search breaks creative flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Solution&lt;/strong&gt;: DM Mode watches what you're writing and proactively suggests relevant encounters—no explicit query needed.&lt;/p&gt;

&lt;h4&gt;
  
  
  How It Works
&lt;/h4&gt;

&lt;p&gt;The DM has a split-pane interface: text editor on the left, contextual suggestions on the right.&lt;/p&gt;

&lt;h4&gt;
  
  
  Context-Aware Filtering
&lt;/h4&gt;

&lt;p&gt;The key is the filter: &lt;code&gt;type:Enemy OR type:Trap&lt;/code&gt;. DM Mode doesn't show classes, races, or spells—only threats. The system understands the &lt;em&gt;context&lt;/em&gt; of what a DM needs.&lt;/p&gt;

&lt;p&gt;When the DM writes "spider webs," they don't have to search for spider monsters. The suggestions panel automatically shows Giant Spiders, Phase Spiders, Ettercaps, and Web Traps.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Creative Flow
&lt;/h4&gt;

&lt;p&gt;The DM keeps writing. Suggestions update silently in the periphery. When they need an encounter, the perfect option is already waiting. No explicit search. No breaking concentration. No dialogue.&lt;/p&gt;

&lt;p&gt;This is intelligence &lt;em&gt;injected into&lt;/em&gt; the creative workflow, not &lt;em&gt;replacing&lt;/em&gt; it.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Party Builder: Proactive Composition Analysis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: A D&amp;amp;D party needs balance. Without a healer, everyone dies. Without damage, combat takes forever. Without a tank, the squishy wizard gets targeted. But most groups don't realize they have a problem until they're mid-dungeon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Solution&lt;/strong&gt;: Party Builder proactively analyzes group composition and surfaces warnings before the adventure begins.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Experience smart, non-conversational assistance:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://the-adventurer-s-codex.vercel.app" rel="noopener noreferrer"&gt;Enter The Forge →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build a character. Run an encounter. Assemble a party. See how contextual intelligence enhances every step—without a single chat bubble.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Pattern
&lt;/h2&gt;

&lt;p&gt;All three experiences share a common technical approach:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Observe User Context
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The Forge: Track selected class&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;selectedClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSelectedClass&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// DM Mode: Watch text content&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sceneText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSceneText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Party Builder: Monitor party roster&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;party&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setParty&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Derive Intent from Context
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The Forge: User selected Wizard → they want Wizard subclasses&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subclassFilter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`type:Subclass AND parentClass:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selectedClass&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// DM Mode: User is writing a scene → they might need encounters&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encounterFilter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;type:Enemy OR type:Trap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Party Builder: User has 4 characters → analyze their composition&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;roleAnalysis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;analyzePartyRoles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;party&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Proactively Retrieve Relevant Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The Forge: Fetch compatible races sorted by stat bonus&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Configure&lt;/span&gt;
  &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"type:Race"&lt;/span&gt;
  &lt;span class="na"&gt;optionalFilters&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`statBonuses:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;primaryStat&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Boost matching stats&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// DM Mode: Search monsters matching scene keywords&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SearchBox&lt;/span&gt; &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;debouncedSceneText&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Party Builder: No search needed—analysis is computed from indexed data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recommendations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRecommendationsForMissingRoles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roleAnalysis&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Future
&lt;/h3&gt;

&lt;p&gt;I think this could be fun to keep building the codex and the Algolia features, it's been very exciting learning about how the platform works&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>algoliachallenge</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>The Oracle: A Conversational D&amp;D Character Discovery Experience</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Thu, 29 Jan 2026 04:39:28 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/the-oracle-a-conversational-dd-character-discovery-experience-5bjp</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/the-oracle-a-conversational-dd-character-discovery-experience-5bjp</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/algolia"&gt;Algolia Agent Studio Challenge&lt;/a&gt;: Consumer-Facing Conversational Experiences&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Choice Paralysis
&lt;/h2&gt;

&lt;p&gt;"I want to play a character like Gandalf, but cooler."&lt;/p&gt;

&lt;p&gt;"Something that can heal but also deal damage?"&lt;/p&gt;

&lt;p&gt;"I don't know... maybe like a sneaky magic user?"&lt;/p&gt;

&lt;p&gt;These are real things players say when creating Dungeons &amp;amp; Dragons characters. They know the &lt;em&gt;feeling&lt;/em&gt; they want, but they're facing 12 classes, dozens of races, and hundreds of subclasses. Traditional character builders force players to browse categories and read walls of text. But that's not how people actually think about characters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Oracle&lt;/strong&gt; is my answer: a conversational interface that lets players describe their fantasy in natural language and receive intelligent, contextually relevant suggestions powered by Algolia's search capabilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is The Oracle?
&lt;/h2&gt;

&lt;p&gt;The Oracle is a guided discovery tool disguised as a mystical advisor. Players approach it like they would a wise sage in a fantasy tavern:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Player&lt;/strong&gt;: "I want to be a frontline warrior who uses divine magic to protect allies"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Oracle&lt;/strong&gt;: &lt;em&gt;Returns Paladin class, Oath of Devotion subclass, Protection Fighting Style, and compatible races like Human and Dragonborn&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The experience feels like a conversation, but under the hood, it's powered by Algolia's intelligent search with the richly indexed D&amp;amp;D knowledge base.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try The Oracle
&lt;/h2&gt;

&lt;p&gt;Experience the conversational character discovery yourself:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://the-adventurer-s-codex.vercel.app" rel="noopener noreferrer"&gt;Consult The Oracle →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Describe your fantasy. Receive your destiny.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Conversational Flow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Stage 1: The Open Question
&lt;/h3&gt;

&lt;p&gt;The Oracle opens with a search interface that invites natural language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│  🔮 The Oracle                                          │
│                                                         │
│  "Describe your ideal adventurer, and I shall reveal    │
│   the path that awaits you..."                          │
│                                                         │
│  ┌───────────────────────────────────────────────────┐  │
│  │ I want to be a wise healer who protects nature    │  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
└─────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Players can type anything—there's no wrong input. The Oracle interprets intent, not just keywords.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 2: Guided Playstyle Prompts
&lt;/h3&gt;

&lt;p&gt;For players who need a starting point, we provide conversational prompts disguised as playstyle choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"I want to stand in front and take hits"&lt;/strong&gt; → Frontline Fighter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"I want to deal massive damage"&lt;/strong&gt; → Damage Dealer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"I want to cast powerful spells"&lt;/strong&gt; → Spellcaster&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"I want to keep my allies alive"&lt;/strong&gt; → Healer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"I want to be sneaky and cunning"&lt;/strong&gt; → Stealth &amp;amp; Cunning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"I want to talk my way through problems"&lt;/strong&gt; → Face &amp;amp; Diplomat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each playstyle triggers a semantically rich query that surfaces relevant options. When a player clicks "Healer," we don't just search for "healer"—we search for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"healing support restoration life cleric druid divine nature protect ally"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This targeted prompting ensures comprehensive, contextually relevant results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 3: Contextual Results
&lt;/h3&gt;

&lt;p&gt;Results are grouped conversationally, as if The Oracle is explaining options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│  The Oracle has spoken...                               │
│                                                         │
│  📜 RECOMMENDED CLASSES                                 │
│  ┌─────────────────────────────────────────────────┐   │
│  │ 🛡️ Cleric                                        │   │
│  │ "Divine spellcasters who channel the power of   │   │
│  │  their deity to heal wounds and smite enemies"  │   │
│  │  Primary Stat: Wisdom                           │   │
│  └─────────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────────┐   │
│  │ 🌿 Druid                                         │   │
│  │ "Guardians of nature who wield primal magic     │   │
│  │  and can transform into beasts"                 │   │
│  │  Primary Stat: Wisdom                           │   │
│  └─────────────────────────────────────────────────┘   │
│                                                         │
│  🧬 COMPATIBLE RACES                                    │
│  ┌─────────────────────────────────────────────────┐   │
│  │ 🧝 Wood Elf (+2 DEX, +1 WIS)                     │   │
│  │ 🌲 Firbolg (+2 WIS, +1 STR)                      │   │
│  └─────────────────────────────────────────────────┘   │
│                                                         │
│  ⚔️ RELATED OPTIONS                                     │
│  │ Life Domain • Circle of Dreams • Healing Word   │    │
│                                                         │
└─────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stage 4: Refinement Through Dialogue
&lt;/h3&gt;

&lt;p&gt;The conversation continues. If the player selects "Druid," The Oracle responds with follow-up context:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A Druid who protects nature... Perhaps you seek the &lt;strong&gt;Circle of the Shepherd&lt;/strong&gt;, who calls upon spirit guardians, or the &lt;strong&gt;Circle of Dreams&lt;/strong&gt;, connected to the mystical Feywild?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each selection narrows the search, creating a back-and-forth dialogue that guides players to their perfect character.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Algolia Powers the Conversation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Rich Data Indexing
&lt;/h3&gt;

&lt;p&gt;The D&amp;amp;D codex is indexed with semantic richness that enables natural language understanding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cleric"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Class"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Divine spellcasters who channel deity power"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"healer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"support"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"divine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"holy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"priest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"restoration"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="s2"&gt;"protection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"light"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"life"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"armored caster"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wisdom"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"primaryStat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wisdom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"playstyles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"healer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"support"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"frontline"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fantasy_archetypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"priest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"paladin-lite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"battle medic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"holy warrior"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a player types "I want to be a battle medic," Algolia matches against &lt;code&gt;fantasy_archetypes&lt;/code&gt;, &lt;code&gt;tags&lt;/code&gt;, and &lt;code&gt;description&lt;/code&gt;—not just the class name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Synonym Configuration
&lt;/h3&gt;

&lt;p&gt;We configured synonyms in Algolia to handle player language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gandalf =&amp;gt; wizard, wise, magic, staff, grey
legolas =&amp;gt; ranger, archer, elf, dexterity, bow
tank =&amp;gt; defender, frontline, armor, shield, protection
glass cannon =&amp;gt; damage, squishy, powerful, fragile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Future
&lt;/h3&gt;

&lt;p&gt;I hope to keep building on this platform as it's been a blast getting to know the Algolia system&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>algoliachallenge</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Portfolio Dungeon Crawler</title>
      <dc:creator>austin amento</dc:creator>
      <pubDate>Mon, 19 Jan 2026 01:06:05 +0000</pubDate>
      <link>https://forem.com/austin_amento_860aebb9f55/portfolio-dungeon-crawler-4286</link>
      <guid>https://forem.com/austin_amento_860aebb9f55/portfolio-dungeon-crawler-4286</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/new-year-new-you-google-ai-2025-12-31"&gt;New Year, New You Portfolio Challenge Presented by Google AI&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;My name is Austin, I am a self taught developer who lives in the Pacific North West. I love learning new things related to development and enjoy playing with new AI models.&lt;/p&gt;

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

&lt;p&gt;I thought it would be fun to make my resume be hidden in a DnD text game. Where you will need to explore the dungeon to fully unlock the full portfolio. I wanted to create an experience that you can have unique experiences each time (thanks to the gemini DM). After uncovering the mysteries of the dungeon I figured you need to end the experience with a boss battle to feel complete. Give it a try and let me know what you think!&lt;/p&gt;

&lt;h2&gt;
  
  
  Portfolio
&lt;/h2&gt;

&lt;p&gt;Feel free to explore the dungeon and experience my portfolio below!&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://dungeon-developer-465709887808.us-west1.run.app/"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;




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

&lt;p&gt;I built this using AI studio and deploying on Google Cloud. I have really enjoyed building some MVPs using AI Studio. This was inspired by a solo project I'am working on which is a Solo Dnd experience that I am hoping to release in the coming weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm Most Proud Of
&lt;/h2&gt;

&lt;p&gt;Im really excited for the way you can uncover hidden parts of your journal (my portfolio) as you explore the dungeon. Also I wanted a fun way to wrap up the experience once all the information was discovered so I included a boss fight to signify you have completed the dungeon. &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
  </channel>
</rss>
