<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paul Ayoade</title>
    <description>The latest articles on DEV Community by Paul Ayoade (@phoniexcryptz001).</description>
    <link>https://dev.to/phoniexcryptz001</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3111065%2F09de97c5-afb8-4bb3-ade2-641380434f89.png</url>
      <title>DEV Community: Paul Ayoade</title>
      <link>https://dev.to/phoniexcryptz001</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/phoniexcryptz001"/>
    <language>en</language>
    <item>
      <title>I Built a 3D Home for Memories, and Gave the AI Boundaries</title>
      <dc:creator>Paul Ayoade</dc:creator>
      <pubDate>Wed, 28 Oct 2026 12:57:56 +0000</pubDate>
      <link>https://dev.to/phoniexcryptz001/i-built-a-3d-home-for-memories-and-gave-the-ai-boundaries-41ma</link>
      <guid>https://dev.to/phoniexcryptz001/i-built-a-3d-home-for-memories-and-gave-the-ai-boundaries-41ma</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;A room can be empty and still be full of someone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The chair they always chose. The table that became a classroom after dinner. The lamp they left on while reading “just one more page.”&lt;/p&gt;

&lt;p&gt;We can save photographs of those things. But the little stories that give them meaning often live somewhere else: in a conversation, an unnamed file, or somebody’s memory.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;The Unfinished Room&lt;/strong&gt; to give those stories a place you can enter.&lt;/p&gt;

&lt;p&gt;It is an interactive 3D memory-room creator. Start with an empty room, furnish it yourself or ask AI for an arrangement, and attach memories to meaningful objects. Visitors can open those objects, read the original words, and gradually fill a discovery journal.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Ghost in the Machine&lt;/strong&gt;, I chose the presence that familiar objects can hold. A quiet room, with stories waiting inside it.&lt;/p&gt;

&lt;p&gt;The room is called &lt;em&gt;unfinished&lt;/em&gt; because a memory does not need every detail filled in to deserve keeping.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fstnn4a6dsttgcsxjz8dp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fstnn4a6dsttgcsxjz8dp.jpg" alt="Home at Six, a furnished living-room example with three memory hotspots and room navigation controls" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/0jmkhyr1wgn5kv9onya0.jpg" rel="noopener noreferrer"&gt;Open the original full-size image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The current gallery, shown in the browser’s simplified rendering mode.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Watch: explore the room and its memories (55 seconds).&lt;/strong&gt; Real website footage, edited for pacing.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Start here: &lt;a href="https://unfinishedroom.phoenixreborn.tech/gallery/" rel="noopener noreferrer"&gt;Explore the seven-room gallery&lt;/a&gt;.&lt;/strong&gt; No account or AI request is needed to browse it.&lt;/p&gt;

&lt;p&gt;Every room is furnished using the app’s own tools and includes &lt;strong&gt;three clearly labelled fictional memories&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Room&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;What it remembers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dining&lt;/td&gt;
&lt;td&gt;The Sunday Table&lt;/td&gt;
&lt;td&gt;Family lunches and a place kept for visitors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Living&lt;/td&gt;
&lt;td&gt;Home at Six&lt;/td&gt;
&lt;td&gt;The ordinary ritual of coming home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parlour&lt;/td&gt;
&lt;td&gt;The Lagoon Parlour&lt;/td&gt;
&lt;td&gt;Neighbours, conversation and weekend visits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bedroom&lt;/td&gt;
&lt;td&gt;The First Morning&lt;/td&gt;
&lt;td&gt;Finding your feet in a first apartment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reading&lt;/td&gt;
&lt;td&gt;One More Page&lt;/td&gt;
&lt;td&gt;Books, borrowed stories and evening light&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Study&lt;/td&gt;
&lt;td&gt;Small Desk, Big Plans&lt;/td&gt;
&lt;td&gt;First projects and useful failed attempts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Music&lt;/td&gt;
&lt;td&gt;The Last Record Tonight&lt;/td&gt;
&lt;td&gt;Listening rituals and the pause after a song&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Open a preview, turn the room, and select a memory. If a room feels like a useful starting point, &lt;strong&gt;make a copy to edit&lt;/strong&gt;. Browsing and copying do not overwrite your saved room; saving a copied draft is a separate action.&lt;/p&gt;

&lt;p&gt;One fictional memory in &lt;em&gt;The Sunday Table&lt;/em&gt; says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nobody remembers who first insisted that there should always be room for one more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the kind of detail I wanted the room to hold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other ways in:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://unfinishedroom.phoenixreborn.tech/create/" rel="noopener noreferrer"&gt;Build your own room&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://unfinishedroom.phoenixreborn.tech/room/" rel="noopener noreferrer"&gt;Explore the original five-object archive&lt;/a&gt;, including opt-in Gemma questions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2bo1120b6clgdeixrsv4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2bo1120b6clgdeixrsv4.jpg" alt="The evening sofa memory opens with its story and an explicit fictional-example label" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/7z67zz3kida2n1cq4849.jpg" rel="noopener noreferrer"&gt;Open the original full-size image&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/PHONIEXz/the-unfinished-room" rel="noopener noreferrer"&gt;View the repository on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The project’s code is MIT-licensed. The optional Meshy-generated radio asset has its own attribution and licence notice in the repository.&lt;/p&gt;

&lt;p&gt;Useful places to inspect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/PHONIEXz/the-unfinished-room/blob/main/web/showcases.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;web/showcases.mjs&lt;/code&gt;&lt;/a&gt;: the seven example rooms and their fictional source texts.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PHONIEXz/the-unfinished-room/blob/main/web/room-planning.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;web/room-planning.mjs&lt;/code&gt;&lt;/a&gt;: furniture relationships.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PHONIEXz/the-unfinished-room/blob/main/src/arrange-model.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;src/arrange-model.mjs&lt;/code&gt;&lt;/a&gt;: generation, validation and bounded repair.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PHONIEXz/the-unfinished-room/blob/main/src/layout-recovery.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;src/layout-recovery.mjs&lt;/code&gt;&lt;/a&gt;: preserving existing objects when a model gets its lists wrong.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  AI proposes a room. The app decides what it can safely use.
&lt;/h3&gt;

&lt;p&gt;The creator uses &lt;strong&gt;Google Gemma&lt;/strong&gt; and &lt;strong&gt;GPT-OSS 20B through Groq&lt;/strong&gt;, both open-weight models, to turn a room brief into structured layout proposals.&lt;/p&gt;

&lt;p&gt;A request can be as ordinary as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A modern dining room with a big wooden dining table and six dining chairs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI works with a finite furniture catalogue, materials, room dimensions and openings. It returns a plan that the app checks, renders as a preview, and leaves for the user to review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preview → review → apply → save.&lt;/strong&gt; Each step has a purpose. Generation never silently replaces the room.&lt;/p&gt;

&lt;p&gt;I added Groq after seeing provider failures during development. Users can choose &lt;strong&gt;Google only&lt;/strong&gt;, &lt;strong&gt;Groq only&lt;/strong&gt;, or &lt;strong&gt;Automatic&lt;/strong&gt;. Automatic can try the alternative after a transient failure or unusable result, with consent covering both services. The interface identifies the provider and model that produced the proposal.&lt;/p&gt;

&lt;p&gt;This improves the options available when one service has trouble. It does not make hosted inference failure-proof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch: from a brief to an editable room (55 seconds).&lt;/strong&gt; The recording shows consent, a real Groq proposal after automatic fallback, preview, apply, and editing. Typing and waiting are shortened.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Six chairs taught me that valid JSON is not interior design
&lt;/h3&gt;

&lt;p&gt;An early dining proposal included the requested furniture, but the chairs looked scattered. Our overlap check had found empty spaces for them. It had not understood the table as a gathering point.&lt;/p&gt;

&lt;p&gt;So I added local relationship patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dining chairs sit in aligned rows and face their table.&lt;/li&gt;
&lt;li&gt;Living-room seating groups around a coffee table.&lt;/li&gt;
&lt;li&gt;Bedroom furniture groups around the bed.&lt;/li&gt;
&lt;li&gt;Study and reading layouts coordinate the chair, desk, shelf and light.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The spacing pass now tries moving a furniture group together. If the group cannot fit, unresolved conflicts remain visible and Apply is blocked.&lt;/p&gt;

&lt;p&gt;I also caught a counting mistake: adding six new chairs when two were already present. Explicit totals now count the existing furniture first, trimming only surplus new additions.&lt;/p&gt;

&lt;p&gt;Dining tables come set by default: &lt;strong&gt;plates and cups matched to chair count, apples, and a flower vase&lt;/strong&gt;. The setting is attached to the table, so it moves and scales with it. It can also be switched off.&lt;/p&gt;

&lt;p&gt;These are finite layout rules. They improve common arrangements without claiming to understand every possible design instruction.&lt;/p&gt;

&lt;h3&gt;
  
  
  The model does not get to rewrite your memories
&lt;/h3&gt;

&lt;p&gt;Personal memory text, photos, names, dates and source notes stay in browser storage. AI arrangement receives only the deliberately entered brief and anonymous room geometry. Users can inspect that payload before consenting.&lt;/p&gt;

&lt;p&gt;The app keeps the original object identities and memory records when applying a layout.&lt;/p&gt;

&lt;p&gt;For example, recovery can restore geometry for an existing object that the model omitted:&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="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;preserved&lt;/span&gt;&lt;span class="o"&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;This uses the original input rather than guessing what was lost. The resulting plan still has to pass strict validation. Invalid geometry, unsupported fields and attempts to change existing identities remain errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  The archive can answer with evidence, or leave the question open
&lt;/h3&gt;

&lt;p&gt;The original fictional reading-room demo has a separate Gemma question feature.&lt;/p&gt;

&lt;p&gt;Gemma selects an excerpt from the supplied archive. The server checks its source ID and exact quotation, then displays complete source sentences. Invented quotations are rejected.&lt;/p&gt;

&lt;p&gt;If the archive does not establish an answer, the response should say so. Text matching establishes where words came from; it does not prove that a passage is relevant or historically true. The reader still needs to inspect the source.&lt;/p&gt;

&lt;p&gt;The personal-room viewer has no archive-question form, keeping its memories out of this hosted question flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  A room you can carry out of the browser
&lt;/h3&gt;

&lt;p&gt;I wanted the memories to survive beyond a tab. &lt;strong&gt;The PDF keepsake includes a clean image of the room, its object inventory, photos, memory dates, source notes and unanswered questions.&lt;/strong&gt; Markers and editing controls are left out of the image.&lt;/p&gt;

&lt;p&gt;In the editor, &lt;strong&gt;Export current room PDF&lt;/strong&gt; captures the current draft and viewing angle without replacing the saved room. In the viewer, the keepsake captures the room you are looking at. The browser's &lt;strong&gt;Print / Save as PDF&lt;/strong&gt; action finishes the export.&lt;/p&gt;

&lt;p&gt;The distinction matters: &lt;strong&gt;PDF is the readable, shareable copy. JSON is the backup you can restore and keep editing.&lt;/strong&gt; Both are prepared locally; no AI request is needed to export.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://unfinishedroom.phoenixreborn.tech/keepsake/?example=sunday-table" rel="noopener noreferrer"&gt;Open an example room keepsake&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmkiyld8qvhj74uxxe2ho.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmkiyld8qvhj74uxxe2ho.jpg" alt="Room-image PDF keepsake showing the dining scene, inventory totals and the beginning of its written details" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/f5d4x6ru7ops264ojgwz.jpg" rel="noopener noreferrer"&gt;Open the original full-size image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch: privacy, backup, and the PDF keepsake (55 seconds).&lt;/strong&gt; A saved fictional memory, provider controls, JSON backup, and the room-image export.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  The tools behind the room
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Its actual job&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTML, CSS and vanilla JavaScript&lt;/td&gt;
&lt;td&gt;Pages, editor, controls, gallery and memory interactions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Three.js, OrbitControls and SVGRenderer&lt;/td&gt;
&lt;td&gt;Procedural 3D rooms, camera navigation and simplified rendering where WebGL is unavailable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google AI Studio / Gemma&lt;/td&gt;
&lt;td&gt;Layout proposals and source selection in the fictional archive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Groq / GPT-OSS 20B&lt;/td&gt;
&lt;td&gt;An alternative provider for layout proposals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js and esbuild&lt;/td&gt;
&lt;td&gt;Server-side request handling, automated checks and builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub and Vercel&lt;/td&gt;
&lt;td&gt;Public source, deployment and server-side API functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;.tech&lt;/code&gt; domain&lt;/td&gt;
&lt;td&gt;The public home at &lt;code&gt;unfinishedroom.phoenixreborn.tech&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Meshy&lt;/td&gt;
&lt;td&gt;An optional radio-model experiment in the original demo, with separate attribution&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I used Codex during development for implementation, debugging and test work. I also used GitHub Copilot Chat to inspect a real editor bug: selecting a starter or copying a gallery room left the AI purpose selector on its default. Copilot recommended a guarded mapping/helper fix, which I implemented and tested. &lt;a href="https://github.com/PHONIEXz/the-unfinished-room/blob/main/docs/copilot-contribution.md" rel="noopener noreferrer"&gt;Contribution record&lt;/a&gt;. GitHub Actions installs locked dependencies, runs the tests and builds the app on pushes and pull requests. The gallery stories are original fictional examples prepared for this project. This article was prepared with AI assistance and checked against the repository and recorded test results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verification completed and practical limits
&lt;/h3&gt;

&lt;p&gt;At publication, &lt;strong&gt;108 automated tests pass&lt;/strong&gt;, together with the production build. The tests cover source links, layout validation, retries, recovery, spacing, table settings and all seven gallery rooms.&lt;/p&gt;

&lt;p&gt;Live desktop checks include opening gallery memories, exploring the full room, saving and reloading, and downloading and restoring backups. I also checked room-image export from the viewer and an unsaved draft, and rendered a print-layout sample with its image and source text. Desktop browser-native PDF export is demonstrated in my recorded walkthrough, and I completed the phone PDF-printing check successfully. I also checked that copying a gallery example into the editor left the previously saved room unchanged.&lt;/p&gt;

&lt;p&gt;I completed the current phone checks on October 28, including controls, navigation, visual layout and PDF printing, and reported that everything worked well. These are my manual device checks. The separate cloud-browser checks use simplified rendering and do not independently verify hardware-WebGL shading.&lt;/p&gt;

&lt;p&gt;Practical limits are visible: one room, up to 12 placed objects, a rectangular shell and stylized materials. There is no cloud sync, encrypted memory vault, photorealistic rendering or full walking-route simulation. Browser storage can be cleared, so users should export a JSON backup. The room-image PDF keepsake offers another way to carry the scene and its words out of the app.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;I wanted the room to outlast a particular model endpoint.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Gemma and GPT-OSS are open-weight models. This build accesses them through hosted services, but the model choice and the surrounding validation code are inspectable. Adding Groq put provider choice into the working product rather than leaving it as a future ambition.&lt;/p&gt;

&lt;p&gt;The room archive is versioned JSON: objects, settings, source text and links between them. Users can export that data, and developers can inspect how it is read and validated.&lt;/p&gt;

&lt;p&gt;A developer could adapt the provider layer for self-hosted inference. That is a possible next step, not something this deployment already does. Hosted AI still needs a network connection and is subject to provider limits.&lt;/p&gt;

&lt;p&gt;Keeping personal memories local is an application-design decision. Open weights alone do not provide privacy. The useful combination here is &lt;strong&gt;portable room data, inspectable safeguards, and a model layer that can be changed&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;While testing a dining room, I kept returning to a simple idea: a table becomes meaningful because of the people who gathered around it.&lt;/p&gt;

&lt;p&gt;The gallery’s Sunday lunch is fictional. A visitor’s version might be a real table, a real chair, and a story they have never written down before.&lt;/p&gt;

&lt;p&gt;That is where I hope this project lands: &lt;strong&gt;“I know what I would put in this room.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Unfinished Room gives that thought somewhere to begin. And when a detail is missing, it leaves space for the person who remembers it.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Best Use of GitHub Copilot:&lt;/strong&gt; Copilot Chat assisted the room-purpose synchronization fix, and GitHub Actions automates repository tests and builds. The contribution record distinguishes chat assistance from coding-agent or PR-review automation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma powers structured room proposals and checked source selection in the fictional archive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Best Use of a .tech Domain:&lt;/strong&gt; the live app, gallery and creator are available at &lt;a href="https://unfinishedroom.phoenixreborn.tech/" rel="noopener noreferrer"&gt;unfinishedroom.phoenixreborn.tech&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built by &lt;strong&gt;Paul Ayoade David (Phoenix / PHONIEXz)&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Wow, this is very interesting</title>
      <dc:creator>Paul Ayoade</dc:creator>
      <pubDate>Tue, 27 Oct 2026 16:50:48 +0000</pubDate>
      <link>https://dev.to/phoniexcryptz001/wow-this-is-very-interesting-310c</link>
      <guid>https://dev.to/phoniexcryptz001/wow-this-is-very-interesting-310c</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/googleai/from-prompt-to-deployed-app-in-less-than-2-minutes-dh3" class="crayons-story__hidden-navigation-link"&gt;From prompt to deployed app in less than 2 minutes&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/googleai"&gt;
            &lt;img alt="Google AI logo" 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%2Forganization%2Fprofile_image%2F11026%2F386b14d3-cc9a-4270-aba0-3e41cdfb9d85.jpg" class="crayons-logo__image" width="400" height="400"&gt;
          &lt;/a&gt;

          &lt;a href="/dynamicwebpaige" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&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%2Fuser%2Fprofile_image%2F3279421%2F805246e6-081d-47b6-bb19-515a33770589.jpg" alt="dynamicwebpaige profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/dynamicwebpaige" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Paige Bailey
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Paige Bailey
                
                
              
              &lt;div id="story-author-preview-content-2624745" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/dynamicwebpaige" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3279421%2F805246e6-081d-47b6-bb19-515a33770589.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Paige Bailey&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/googleai" class="crayons-story__secondary fw-medium"&gt;Google AI&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/googleai/from-prompt-to-deployed-app-in-less-than-2-minutes-dh3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 2 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/googleai/from-prompt-to-deployed-app-in-less-than-2-minutes-dh3" id="article-link-2624745"&gt;
          From prompt to deployed app in less than 2 minutes
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemini"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemini&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/googleai/from-prompt-to-deployed-app-in-less-than-2-minutes-dh3" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;478&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/googleai/from-prompt-to-deployed-app-in-less-than-2-minutes-dh3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              87&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Flow Point: one messy event note, four useful drafts, and the questions we still need to answer</title>
      <dc:creator>Paul Ayoade</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:57:45 +0000</pubDate>
      <link>https://dev.to/phoniexcryptz001/flow-point-one-messy-event-note-four-useful-drafts-and-the-questions-we-still-need-to-answer-3if8</link>
      <guid>https://dev.to/phoniexcryptz001/flow-point-one-messy-event-note-four-useful-drafts-and-the-questions-we-still-need-to-answer-3if8</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;One school event. Four documents. The same details copied over and over.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a teacher, this is the kind of work I wanted to reduce. A rough event note becomes an invitation, a programme, a preparation checklist and a budget. Then somebody changes the time or the number of refreshments, and each document needs another check.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Flow Point&lt;/strong&gt; to prepare that first draft and help me review what changes next.&lt;/p&gt;

&lt;p&gt;Write your event in ordinary language. Choose &lt;strong&gt;Gemma through Google&lt;/strong&gt; or &lt;strong&gt;GPT-OSS through Groq&lt;/strong&gt;. Flow Point prepares the pack, keeps unanswered questions visible, calculates costs in code and lets you edit every section before exporting it.&lt;/p&gt;

&lt;p&gt;The important boundary is simple: &lt;strong&gt;a draft is not an approved plan, and an unknown price is not zero.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flrsti4xrm5ps4ejgjgcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flrsti4xrm5ps4ejgjgcg.png" alt="Full-page Notes editor containing a fictional event brief" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An edited fictional sample. No AI request was made for this capture.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;&lt;a href="https://flowpoint.phoenixreborn.tech/workspace" rel="noopener noreferrer"&gt;Try Flow Point&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://flowpoint.phoenixreborn.tech/judge" rel="noopener noreferrer"&gt;Judge guide and reproducible brief&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://github.com/PHONIEXz/flow-point" rel="noopener noreferrer"&gt;Source code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No account is required. If a provider is unavailable, the clearly labelled hand-authored sample lets you explore editing, review and PDF export without an AI call. It is never presented as generated output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch: notes to preparation pack, 48 seconds
&lt;/h3&gt;

&lt;p&gt;A quick tour of Notes, model choice, the four documents and the review boundary. The sample sections are labelled; this is not a fresh AI-generation recording.&lt;/p&gt;

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

&lt;p&gt;The workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write the notes.&lt;/strong&gt; Include the facts you know and leave unknowns explicit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prepare the pack.&lt;/strong&gt; Generation runs in three steps: facts/checklist/budget, invitation, then run of show.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the sources.&lt;/strong&gt; Source cards show exact note excerpts when available. A matching quote is evidence to inspect, not proof that the model understood it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply changes.&lt;/strong&gt; Update Pack preserves a previous version for comparison and restoration. Questions omitted by the model stay open until explicitly resolved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review and export.&lt;/strong&gt; Download the complete pack or each document separately as PDF. Filenames begin with the event title and have a unique suffix. Markdown includes readable currency, review issues, open questions and source evidence; CSV supports the budget.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnsp427ryc5c15pt9iuur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnsp427ryc5c15pt9iuur.png" alt="Current provider selector" width="799" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A small example you can check
&lt;/h3&gt;

&lt;p&gt;The fictional Cedar School Reading Day screenshots show an edited sample, not a new model run. Fifty refreshments at NGN 300 and fifty programmes at NGN 100 give &lt;strong&gt;NGN 20,000&lt;/strong&gt;. With a &lt;strong&gt;NGN 30,000&lt;/strong&gt; limit, the remaining allowance is &lt;strong&gt;NGN 10,000&lt;/strong&gt;. Missing task owners and due dates remain unresolved and block approval.&lt;/p&gt;

&lt;p&gt;The invitation supports formal block-letter or informal layout. Optional sender/recipient details come from the user, while the letter date stays separate from the event date.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7hly1cd4se0i9k8c52s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7hly1cd4se0i9k8c52s.png" alt="Actual invitation PDF with a formal address block, subject, paragraphs and one signatory" width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An excerpt from an actual local app export of the fictional Cedar sample. It remains a draft requiring review.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F57tgqur0k0n9t1ac8gnu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F57tgqur0k0n9t1ac8gnu.png" alt="Sample budget with NGN 20,000 total and NGN 10,000 allowance" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What happened in a real model run
&lt;/h3&gt;

&lt;p&gt;A recorded Groq/GPT-OSS run used the fictional &lt;strong&gt;Willow Skills Exchange&lt;/strong&gt;. Its update replaced Lara Chen with Nora Cole, changed eight kits to ten at CAD 12.50 each and changed room hire from CAD 0 to CAD 90. The updated cost became &lt;strong&gt;CAD 215&lt;/strong&gt; against a &lt;strong&gt;CAD 200&lt;/strong&gt; limit. The application blocked approval for the overspend.&lt;/p&gt;

&lt;p&gt;Both Willow operations passed all &lt;strong&gt;54 declared checks combined&lt;/strong&gt;. The same assistant authored the briefs and expectations; this is one recorded case, not an independent accuracy score. &lt;a href="https://github.com/PHONIEXz/flow-point/tree/main/docs/evidence/quality-v4-2026-10-24" rel="noopener noreferrer"&gt;Inspect the raw evidence and evaluation limits&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch: update and review, 48 seconds
&lt;/h3&gt;

&lt;p&gt;This clip explains the recorded Willow update and overspend, then distinguishes it from the current sample interface and software-tested recovery controls.&lt;/p&gt;

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

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

&lt;p&gt;The browser calls a &lt;strong&gt;Node.js service on Render&lt;/strong&gt;. That service keeps API keys off the client, routes requests to the selected hosted model, validates the result and creates files with &lt;strong&gt;PDFKit&lt;/strong&gt;. Budget arithmetic, approval checks and export filenames are handled by code.&lt;/p&gt;

&lt;p&gt;The model handles varied language and draft wording. Code checks structure, dates, programme anchors, supplied budget details and unresolved review items. Neither replaces a person's source review.&lt;/p&gt;

&lt;p&gt;Completed generation steps save in the browser when storage is available. Retrying the same input can reuse those steps. A failed replacement leaves the previous pack intact. Up to &lt;strong&gt;12 named packs&lt;/strong&gt; can be saved in the same browser; there is no cross-device sync, so exported backups matter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code: money calculations stay outside the model
&lt;/h3&gt;

&lt;p&gt;The model proposes budget entries; JavaScript calculates the totals. This excerpt from &lt;a href="https://github.com/PHONIEXz/flow-point/blob/main/src/plan.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;src/plan.mjs&lt;/code&gt;&lt;/a&gt; counts missing prices separately from the known subtotal:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unknownPrices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitCostMinor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;knownTotalMinor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unitCostMinor&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prices are stored as integer minor units. NGN 300 is stored as 30,000 kobo, avoiding floating-point money arithmetic. The zero in this sum means an unpriced item adds nothing to the &lt;strong&gt;known subtotal&lt;/strong&gt;. Its actual price stays &lt;code&gt;null&lt;/code&gt;, and the missing-price flag keeps the budget incomplete. A confirmed zero-priced item is different.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code: approval is earned by this exact version
&lt;/h3&gt;

&lt;p&gt;The approval function in the same file runs the review again before issuing a fingerprint:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;approvePlan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;review&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reviewPlan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Resolve review issues before approval&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fingerprint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fingerprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;approvedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&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;Unassigned tasks, missing due dates, unpriced items, overspending and other recorded review issues block approval. The fingerprint binds approval to the checked content. Editing that content requires another review. This does not establish that every sentence is true; the organizer must still compare it with the source.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyoxuc9lyuk3xbtdf1uwd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyoxuc9lyuk3xbtdf1uwd.png" alt="Manual source-review panel showing facts still awaiting review" width="800" height="742"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The sample has manual facts still to review. A Source card is a place to inspect evidence, not an automatic correctness stamp.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why I added Groq
&lt;/h3&gt;

&lt;p&gt;During development, Google-hosted Gemma sometimes returned HTTP 500 or timed out. Groq gave users another open-weight model option, but it also reached quota limits. Adding a second provider did not remove the need for careful failure handling.&lt;/p&gt;

&lt;p&gt;The current release uses &lt;strong&gt;45-second attempt deadlines&lt;/strong&gt;, bounded retries and a short circuit pause after repeated failures. Optional automatic fallback asks for &lt;strong&gt;fresh permission covering both Google and Groq&lt;/strong&gt;. Existing single-provider consent never expands silently. Each generation step records the actual provider and model used. Invalid content is rejected, and failures never create fake output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4o5ala75moanv3jn41ew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4o5ala75moanv3jn41ew.png" alt="Optional combined consent for provider fallback" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Code: fallback requires permission, not just another key
&lt;/h3&gt;

&lt;p&gt;In &lt;a href="https://github.com/PHONIEXz/flow-point/blob/main/src/resilience.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;src/resilience.mjs&lt;/code&gt;&lt;/a&gt;, the alternate provider only enters the attempt list when fallback was explicitly allowed and its server key exists:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alternate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google&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="s1"&gt;groq&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="s1"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;choices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;allowFallback&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;alternate&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;alternate&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;With fallback off, only the selected provider is tried. With it on, the alternate can handle an eligible provider failure. The surrounding code stops on cancellation or invalid model content and records the provider/model actually used. It never substitutes a sample or invents a result to make the request look successful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code update: a model refusal is not a provider outage
&lt;/h3&gt;

&lt;p&gt;The latest &lt;a href="https://github.com/PHONIEXz/flow-point/pull/2" rel="noopener noreferrer"&gt;merged fix&lt;/a&gt; gives non-success candidate finishes an explicit error code in &lt;a href="https://github.com/PHONIEXz/flow-point/blob/main/src/gemma.mjs" rel="noopener noreferrer"&gt;&lt;code&gt;src/gemma.mjs&lt;/code&gt;&lt;/a&gt;:&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;finishReason&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;finishReason&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;STOP&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="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="mi"&gt;502&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The model did not finish a usable pack. &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Review the request before retrying.&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="s1"&gt;MODEL_BLOCKED&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;This guard follows the separate malformed-response and staged token-limit checks. The fallback runner excludes &lt;code&gt;MODEL_BLOCKED&lt;/code&gt;, so a refusal stops instead of being passed to another provider as though it were a temporary outage. A regression test covers seven non-success finish reasons. The five live retests below ran before this small correction; the correction itself is covered by the software suite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Open Innovation Matters
&lt;/h2&gt;

&lt;p&gt;Gemma and GPT-OSS are open-weight models at the core of the event-drafting workflow. Their available weights make alternative hosting and model inspection possible; the MIT-licensed app exposes its prompts, adapters and validation boundary for others to examine and change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This deployment uses hosted inference. It does not run offline or keep consented event notes exclusively on the device.&lt;/strong&gt; The choice helps someone try the app without downloading a model, while leaving room for a future self-hosted adapter. No offline-performance claim is made.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch: PDFs and the build, 54 seconds
&lt;/h3&gt;

&lt;p&gt;See a real exported letter and the jobs of Render, Gemma, Groq, the .tech address, Copilot, Node.js and PDFKit. Deployment/evidence cards are labelled records, not fabricated provider dashboards.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Tools and Partner Contributions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma:&lt;/strong&gt; interprets event notes and proposes structured facts and wording through Google's hosted API. The adapter remains available alongside GPT-OSS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render:&lt;/strong&gt; hosts the Node web service, server-side provider calls and document exports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.tech domain:&lt;/strong&gt; &lt;a href="https://flowpoint.phoenixreborn.tech/" rel="noopener noreferrer"&gt;flowpoint.phoenixreborn.tech&lt;/a&gt; is the live project address under the domain claimed for this challenge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Copilot Chat:&lt;/strong&gt; inspected the PDF filename changes in &lt;a href="https://github.com/PHONIEXz/flow-point/pull/1" rel="noopener noreferrer"&gt;PR #1&lt;/a&gt;. I evaluated its Unicode and decoded-filename findings and added regression coverage. &lt;a href="https://github.com/PHONIEXz/flow-point/blob/main/docs/copilot-review.md" rel="noopener noreferrer"&gt;The contribution record&lt;/a&gt; distinguishes the actual Chat assistance from an unsuccessful formal review request. Partner-category eligibility is for the organizers to determine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Groq, GitHub, Node.js and PDFKit:&lt;/strong&gt; provide the alternate hosted inference path, public source, server runtime and PDF generation. I am documenting their actual roles, not claiming every tool has a prize category.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Tested, and What Remains
&lt;/h2&gt;

&lt;p&gt;The current suite passes &lt;strong&gt;146 software tests&lt;/strong&gt;, including simulated provider failures, consent boundaries, source handling, checklist completeness, exact arithmetic, exports and draft preservation. Those tests are not an AI accuracy percentage.&lt;/p&gt;

&lt;p&gt;The broader frozen v4 evaluation completed 20 of 24 planned operations, with 13 completed operations passing all declared checks. Targeted v5 completed ten of eleven operations, with six passing all declared checks. Failures and mismatches are retained. Those earlier outcomes remain in the repository. On 25 October, I reran the five previously quota-blocked operations through Groq. &lt;strong&gt;All five completed, with all 166 declared content checks passing and no quota failures in that run.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Retested operation&lt;/th&gt;
&lt;th&gt;Declared content checks passed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Detailed school Update&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Riverside Prepare&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Riverside Update&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ambiguous-date Oak Prepare&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community Update&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All &lt;strong&gt;20 standalone PDF response checks&lt;/strong&gt; passed, along with the five application/approval checks. The PDF checks verify successful responses and valid PDF headers, not visual layout. These are exposed regression cases with unchanged expectations, not an independent model-accuracy score or an uptime guarantee. &lt;a href="https://github.com/PHONIEXz/flow-point/tree/main/docs/evidence/quality-v8-2026-10-25" rel="noopener noreferrer"&gt;Read the scorecard and preserved evidence&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also completed a real-phone usability check and reported healthy fitting/layout and perceived speed. Provider availability and arbitrary wording mistakes remain limitations. Google availability was not retested in this latest run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The payoff is fewer places to start from scratch:&lt;/strong&gt; one note becomes an editable set of drafts, and a later change has a reviewable trail. The organizer still makes the final call.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/PHONIEXz/flow-point/blob/main/docs/final-readiness-2026-10-25.md" rel="noopener noreferrer"&gt;Verification and release record&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built by &lt;strong&gt;Paul Ayoade David&lt;/strong&gt;. I directed the project and used AI assistance for code and this article draft. The application is MIT-licensed; model and hosted-service terms apply separately.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>OutsideClass: A Little Less Screen, a Little More World</title>
      <dc:creator>Paul Ayoade</dc:creator>
      <pubDate>Thu, 08 Oct 2026 18:47:52 +0000</pubDate>
      <link>https://dev.to/phoniexcryptz001/outsideclass-a-little-less-screen-a-little-more-world-2p6k</link>
      <guid>https://dev.to/phoniexcryptz001/outsideclass-a-little-less-screen-a-little-more-world-2p6k</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;A learner can read an explanation of symmetry and still walk past a leaf without noticing either half.&lt;/p&gt;

&lt;p&gt;That gap is where &lt;strong&gt;OutsideClass&lt;/strong&gt; starts.&lt;/p&gt;

&lt;p&gt;I built a learning website that turns a question into something you can notice, compare and explain in the world around you. It uses Google's open-weight &lt;strong&gt;Gemma&lt;/strong&gt; model to prepare an explanation and, when the topic suits it, a short observation activity.&lt;/p&gt;

&lt;p&gt;The learning loop is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ask a question. Read the activity. Put the screen away. Observe. Return with something you noticed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a teacher, I care about what remains after someone closes a lesson. Can they recognise the idea somewhere else? Can they describe their evidence? Can they consider another explanation?&lt;/p&gt;

&lt;p&gt;OutsideClass gives those questions a place in the learning process.&lt;/p&gt;

&lt;p&gt;An activity card provides a focus, manageable steps, safety notes and questions to think about afterwards. Learners can save reflections, attach their own evidence photos, try practice questions and revisit their discoveries in a notebook.&lt;/p&gt;

&lt;p&gt;For example, the prepared pattern activity asks learners to compare two nearly matching halves of a leaf. They do not need to pick it. The interesting part is looking closely enough to notice where the halves agree and where they differ.&lt;/p&gt;

&lt;p&gt;The diagram introduces the comparison. The learner's observation supplies the evidence.&lt;/p&gt;

&lt;p&gt;OutsideClass is designed for &lt;strong&gt;learners, parents and teachers&lt;/strong&gt;. Activities can be adapted to the time available, weather, time of day and a family or classroom group. Seated and window-based participation are available too.&lt;/p&gt;

&lt;p&gt;The aim is to make the screen a starting point, then give attention back to the world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A little less screen. A little more world.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;&lt;a href="https://outsideclass-phoenix.vercel.app/" rel="noopener noreferrer"&gt;Try OutsideClass&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://youtu.be/aYUbbZnnJ-I" rel="noopener noreferrer"&gt;Watch the ten-minute walkthrough on YouTube&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The walkthrough covers activities, the timer, reflections, practice questions, notebook backups, image consent and Updates. Its examples are demonstrations, not a report of a completed outdoor lesson.&lt;/p&gt;

&lt;p&gt;You can try the website without signing up or providing a phone number. Start with a labelled sample, read its safety notes, make a suitable observation and save what you noticed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Activities&lt;/strong&gt; and choose a labelled sample, or ask your own learning question.&lt;/li&gt;
&lt;li&gt;Select how you will participate and how much time you have.&lt;/li&gt;
&lt;li&gt;Read the activity and its safety notes before starting.&lt;/li&gt;
&lt;li&gt;Observe in a suitable place, then return with a reflection.&lt;/li&gt;
&lt;li&gt;Save the card in &lt;strong&gt;Notebook&lt;/strong&gt; and try its practice questions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Three prepared samples let visitors explore the format without making a fresh model request. They are clearly labelled as samples.&lt;/p&gt;

&lt;p&gt;The current app also includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An activity timer with pause and recovery after refresh.&lt;/li&gt;
&lt;li&gt;Reflections and locally stored evidence photos.&lt;/li&gt;
&lt;li&gt;Practice questions with feedback.&lt;/li&gt;
&lt;li&gt;Saved activities and return visits to named spots.&lt;/li&gt;
&lt;li&gt;Notebook downloads and restoration.&lt;/li&gt;
&lt;li&gt;Printable lessons and classroom activity packs.&lt;/li&gt;
&lt;li&gt;Optional image questions with consent before sending.&lt;/li&gt;
&lt;li&gt;An Updates page with search, category filters and RSS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Personalisation is deliberately simple. An optional first name or nickname and a Learner, Teacher or Parent role can personalise the greeting. These preferences stay in the browser. They are not a verified account and do not provide automatic device sync.&lt;/p&gt;

&lt;p&gt;I have also prepared a ten-minute walkthrough covering the learning flow, notebook, practice, image consent and Updates. Its examples are demonstrations, not a report of a completed outdoor lesson.&lt;/p&gt;

&lt;p&gt;The walkthrough was assembled using Brag, Hyperframes and F5-TTS, with my own voice recording as the narration reference.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/PHONIEXz/OutsideClass" rel="noopener noreferrer"&gt;OutsideClass on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The repository is public, and the application source is &lt;strong&gt;MIT-licensed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The repository and its first commits were created on &lt;strong&gt;October 6, 2026&lt;/strong&gt;, during this challenge.&lt;/p&gt;

&lt;p&gt;The README covers local setup, Gemma configuration, privacy boundaries and current limitations. The prepared samples can run locally without an API key.&lt;/p&gt;

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

&lt;p&gt;The starting configuration uses &lt;strong&gt;&lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt;&lt;/strong&gt;, served through Google's Gemini API.&lt;/p&gt;

&lt;p&gt;The API is the hosting interface. The model requested by OutsideClass is &lt;strong&gt;Gemma&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Gemma generates learning explanations, observation activities and practice questions from the learner's question and selected context. Follow-up requests can include the earlier answer, while return visits can use the learner's selected observation context.&lt;/p&gt;

&lt;p&gt;This makes Gemma part of the main learning flow: it prepares the material that the learner takes into an observation and returns to afterwards.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keeping generated content usable
&lt;/h3&gt;

&lt;p&gt;The server validates bounded inputs, applies a request timeout and asks for a structured response. It checks the returned content before rendering it.&lt;/p&gt;

&lt;p&gt;The API key stays on the server.&lt;/p&gt;

&lt;p&gt;Safety guidance also lives in application code. The app can add relevant notes for children, groups, weather and participation choices, rather than depending entirely on a generated response to remember them.&lt;/p&gt;

&lt;p&gt;Generated explanations can still be wrong. Adults should review lessons for children, and practice results are learning feedback rather than formal grades.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keeping the notebook local
&lt;/h3&gt;

&lt;p&gt;OutsideClass uses HTML, CSS and browser JavaScript, with a Node.js development server and a Vercel API handler for hosted inference. The application has no runtime npm dependencies.&lt;/p&gt;

&lt;p&gt;Saved cards and reflections live in browser localStorage. Evidence photos use IndexedDB. A service worker caches supported pages and resources after an online visit.&lt;/p&gt;

&lt;p&gt;There are two separate image flows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Question images:&lt;/strong&gt; up to two selected images, resized before sending to Google and requiring consent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notebook evidence:&lt;/strong&gt; photos attached to saved work, kept locally and not automatically sent to the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Weather and time of day are selected manually. The app does not require GPS, camera or microphone access.&lt;/p&gt;

&lt;p&gt;A lesson pack excludes personal reflections and photos. A notebook backup can contain them. Keeping those exports separate helps teachers share a lesson without accidentally sharing a learner's private work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing the parts that could lose someone's work
&lt;/h3&gt;

&lt;p&gt;An attractive activity card is not enough if a learner loses the reflection they just wrote.&lt;/p&gt;

&lt;p&gt;During testing, finishing a timer after returning to its card exposed a problem with unsaved practice answers. I fixed that flow so timer completion preserves the open card's work.&lt;/p&gt;

&lt;p&gt;Notebook capacity also refuses new cards at the limit instead of silently removing older discoveries.&lt;/p&gt;

&lt;p&gt;The current release passes &lt;strong&gt;72 automated tests and its build check&lt;/strong&gt;. Coverage includes response validation, provider failures, image consent, practice scoring, storage failures, timer recovery and backup restoration.&lt;/p&gt;

&lt;p&gt;Desktop browser checks exercised live Gemma responses and restoring notes, practice results and evidence photos into a fresh notebook. I also tested the app on my phone, and the flows I tried worked.&lt;/p&gt;

&lt;p&gt;The current limits are clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fresh Gemma requests need internet.&lt;/li&gt;
&lt;li&gt;Cached pages, prepared samples and saved work can work offline after an online visit.&lt;/li&gt;
&lt;li&gt;The timer is not a background alarm.&lt;/li&gt;
&lt;li&gt;Notebook transfer uses downloaded backups, not automatic cloud sync.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;For me, the value is being able to inspect and change the learning process around an open-weight model.&lt;/p&gt;

&lt;p&gt;Gemma's available weights leave room to explore a different inference deployment later, including local inference on suitable hardware. That option matters for an app intended to move learning beyond a reliable internet connection.&lt;/p&gt;

&lt;p&gt;For this release, I chose hosted inference so learners can open the website without downloading a model. OutsideClass does not currently run Gemma locally, and changing providers would require adapting the server integration.&lt;/p&gt;

&lt;p&gt;Opening the application source is equally useful.&lt;/p&gt;

&lt;p&gt;Someone can inspect how questions become activities, read the safety rules, change the prompts, select another supported Gemma model or build on the notebook tools. A teacher working with a different curriculum can examine the assumptions and adapt them.&lt;/p&gt;

&lt;p&gt;The combination gives others access to the application logic today and a path to experiment with the model's deployment in the future.&lt;/p&gt;

&lt;p&gt;The privacy boundaries come from the application design: notebook reflections and evidence photos stay local, while submitted questions and consented question images are processed by Google.&lt;/p&gt;

&lt;p&gt;That boundary needs to be explained honestly.&lt;/p&gt;

&lt;p&gt;For this challenge, the working contribution is a learning loop that connects an open-weight model to observation, evidence and reflection.&lt;/p&gt;

&lt;p&gt;The next question should sometimes come from something the learner noticed outside, rather than another suggestion on a screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;The GitHub repository includes the implementation, commit history and verification notes behind the build. A public DevRelay session is not included in this submission.&lt;/p&gt;

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

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

&lt;p&gt;OutsideClass uses Google's Gemma open-weight model to generate its learning explanations, observation activities and practice questions.&lt;/p&gt;

&lt;p&gt;Gemma powers the core feature connecting a learner's question to an activity they can take into the world.&lt;/p&gt;

&lt;p&gt;Gemma is developed by Google. Hosted access is documented in &lt;a href="https://ai.google.dev/gemma/docs/core/gemma_on_gemini_api" rel="noopener noreferrer"&gt;Google's Gemma API guide&lt;/a&gt;. Its model and service terms apply separately from the application's MIT licence.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>MARKET EVIDENCE PROJECT</title>
      <dc:creator>Paul Ayoade</dc:creator>
      <pubDate>Tue, 29 Sep 2026 12:04:38 +0000</pubDate>
      <link>https://dev.to/phoniexcryptz001/-3l0m</link>
      <guid>https://dev.to/phoniexcryptz001/-3l0m</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/phoniexcryptz001/market-evidence-desk-research-with-receipts-25gm" class="crayons-story__hidden-navigation-link"&gt;Market Evidence Desk: Research With Receipts&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/phoniexcryptz001/market-evidence-desk-research-with-receipts-25gm" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Sanity Challenge Path One Submission&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/phoniexcryptz001" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3111065%2F09de97c5-afb8-4bb3-ade2-641380434f89.png" alt="phoniexcryptz001 profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/phoniexcryptz001" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Paul Ayoade
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Paul Ayoade
                
                
              
              &lt;div id="story-author-preview-content-4724420" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/phoniexcryptz001" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3111065%2F09de97c5-afb8-4bb3-ade2-641380434f89.png" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Paul Ayoade&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/phoniexcryptz001/market-evidence-desk-research-with-receipts-25gm" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 29&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/phoniexcryptz001/market-evidence-desk-research-with-receipts-25gm" id="article-link-4724420"&gt;
          Market Evidence Desk: Research With Receipts
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/sanitychallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;sanitychallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/sanity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;sanity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/phoniexcryptz001/market-evidence-desk-research-with-receipts-25gm" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/phoniexcryptz001/market-evidence-desk-research-with-receipts-25gm#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Market Evidence Desk: Research With Receipts</title>
      <dc:creator>Paul Ayoade</dc:creator>
      <pubDate>Tue, 29 Sep 2026 11:53:47 +0000</pubDate>
      <link>https://dev.to/phoniexcryptz001/market-evidence-desk-research-with-receipts-25gm</link>
      <guid>https://dev.to/phoniexcryptz001/market-evidence-desk-research-with-receipts-25gm</guid>
      <description>&lt;p&gt;This is my submission for the &lt;a href="https://dev.to/devteam/join-the-sanity-challenge-2500-in-prizes-for-five-winners-514m"&gt;Sanity Challenge, Path One: Ship an Agent That Queries Real Content&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Market Evidence Desk is a public research tool for questions where a confident answer can be misleading. It focuses on crypto investor protection: proof of reserves, custody, deposit insurance, stablecoins, and the difference between international recommendations and protections actually in force.&lt;/p&gt;

&lt;p&gt;Consider a question that sounds simple: &lt;strong&gt;Can a proof-of-reserves report show that customers’ assets are safe?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kraken describes how a customer can check whether their balance was included in a reserves snapshot. The PCAOB and SEC explain limits that such a snapshot may leave unanswered, including liabilities and what happens outside the snapshot. These publications address different parts of the question. Treating one as the complete answer would mislead a reader.&lt;/p&gt;

&lt;p&gt;The desk connects each dated claim to its original publication and research question. Visitors can inspect those connections themselves, compare attributed positions, and ask an AI agent to draft an answer from the Sanity evidence.&lt;/p&gt;

&lt;p&gt;As checked on October 1, 2026, the &lt;strong&gt;public published Sanity graph contains 101 research questions, 112 linked evidence claims, and 22 source records covering 21 distinct original URLs&lt;/strong&gt;. The relationships matter more than the count: a reader can move from a question to each claim, then to its source, date, excerpt, and recorded review information.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://market-evidence-desk.vercel.app/" rel="noopener noreferrer"&gt;Open Market Evidence Desk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://market-evidence-desk.vercel.app/web/atlas.html" rel="noopener noreferrer"&gt;Browse the evidence atlas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://market-evidence-desk.vercel.app/web/compare.html" rel="noopener noreferrer"&gt;Compare attributed claims&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://market-evidence-desk.vercel.app/web/sources.html" rel="noopener noreferrer"&gt;Inspect the sources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://market-evidence-desk.vercel.app/web/agent.html?case=dispute" rel="noopener noreferrer"&gt;Ask the agent about a disagreement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/947uwSq7p9M" rel="noopener noreferrer"&gt;Watch the video walkthrough&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A three-step test for judges
&lt;/h3&gt;

&lt;p&gt;The public desk requires no sign-in.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://market-evidence-desk.vercel.app/web/agent.html?case=dispute" rel="noopener noreferrer"&gt;AI agent disagreement case&lt;/a&gt; and press &lt;strong&gt;Ask the sources&lt;/strong&gt;. The answer may take up to two minutes. Look at the cited publications and the Sanity tools reported for that run.&lt;/li&gt;
&lt;li&gt;Open &lt;a href="https://market-evidence-desk.vercel.app/web/compare.html" rel="noopener noreferrer"&gt;Compare&lt;/a&gt; to see the positions attributed separately. Follow a claim into the &lt;a href="https://market-evidence-desk.vercel.app/web/research.html" rel="noopener noreferrer"&gt;research desk&lt;/a&gt; or &lt;a href="https://market-evidence-desk.vercel.app/web/sources.html" rel="noopener noreferrer"&gt;sources page&lt;/a&gt;, then inspect its original publication.&lt;/li&gt;
&lt;li&gt;Try the agent’s &lt;strong&gt;live price&lt;/strong&gt; case. The historical source collection has no live market feed. The answer should acknowledge that boundary instead of inventing a current Bitcoin price or a buy recommendation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The guided comparison reads published Sanity records directly, so visitors can still inspect the evidence if the model service is temporarily slow. The research desk labels its fictional demonstration separately from published evidence.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/PHONIEXz/market-evidence-desk" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; · &lt;a href="https://github.com/PHONIEXz/market-evidence-desk/blob/main/README.md" rel="noopener noreferrer"&gt;Architecture, setup, and limitations&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Sanity
&lt;/h2&gt;

&lt;p&gt;I modeled the research as three linked document types in Sanity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;&lt;code&gt;source&lt;/code&gt;&lt;/strong&gt; records an original publication, its URL, publication date, and scope.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;&lt;code&gt;marketEvent&lt;/code&gt;&lt;/strong&gt; represents a focused research question.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;&lt;code&gt;evidenceClaim&lt;/code&gt;&lt;/strong&gt; connects one question to one source. It records the claim, its stance (&lt;code&gt;supports&lt;/code&gt;, &lt;code&gt;conflicts&lt;/code&gt;, or &lt;code&gt;context&lt;/code&gt;), its observation date, and its source-check fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure gives a claim two essential links: &lt;strong&gt;What question does it address? Which publication supports its wording?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The site assembles a dossier from those links and shows where sources discuss different scopes. A company description of a customer snapshot, for example, can appear as context beside regulatory cautions about broader assurance. The interface does not force them into a false yes-or-no vote.&lt;/p&gt;

&lt;p&gt;Sanity Studio is the editing and review surface. The public site reads the &lt;strong&gt;published&lt;/strong&gt; graph through a read-only server route. Claim cards can show an excerpt, its location in the publication, and a recorded editor source check. That check describes an editor’s attestation. It is not an independent audit of the publication or approval of everything the AI might say.&lt;/p&gt;

&lt;p&gt;Question approval and claim source checks are displayed separately. For example, a dossier can show &lt;strong&gt;“Question approved · 3/3 claims source checked”&lt;/strong&gt; while still telling readers to open the original publications and assess the limits of the evidence themselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where Sanity Context enters
&lt;/h3&gt;

&lt;p&gt;I pointed Sanity Context at the &lt;code&gt;production&lt;/code&gt; dataset and a separate SEC investor-alert page to build the &lt;strong&gt;Market Evidence Desk Sourcebook Knowledge Base&lt;/strong&gt;. Its dataset selection is bounded to fit the Knowledge Base document budget. The published dataset remains available to the agent through a Context MCP endpoint that supports GROQ queries.&lt;/p&gt;

&lt;p&gt;For an agent question, the Python agent uses two Sanity Context tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;groq_query&lt;/code&gt;&lt;/strong&gt; retrieves the linked, published question, claim, and source records.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;knowledge_base_read&lt;/code&gt;&lt;/strong&gt; retrieves relevant Sourcebook entries and their source context.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The agent then drafts an answer that attributes positions and provides source links. The server checks that both required retrieval tools ran before returning a completed research answer. The public interface displays the tool names reported for the run. Model and organization credentials stay on the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the structure changes the answer
&lt;/h3&gt;

&lt;p&gt;A keyword search for “proof of reserves safe” can retrieve several pages. By itself, it does not tell the agent which statement is a company’s account of its own process, which is a regulator’s caution, which research question each statement addresses, or whether a claim was checked against a specific passage.&lt;/p&gt;

&lt;p&gt;The Sanity records supply those connections. GROQ follows a claim’s references to its question and source. The Sourcebook supplies navigable, source-linked context. The agent can use both to explain &lt;strong&gt;what each publication establishes and what it leaves open&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A second test concerns two SEC publications dated April 4, 2025. One describes a Division of Corporation Finance staff view of stablecoin issuer practices involving reserve reports. Commissioner Caroline A. Crenshaw challenges what such reports demonstrate. The desk identifies the speakers and keeps their positions distinct. It does not present either publication as a finding that a particular stablecoin is safe today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sanity Project Details
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sanity project ID:&lt;/strong&gt; &lt;code&gt;cxjysvlq&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dataset:&lt;/strong&gt; &lt;code&gt;production&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public dataset:&lt;/strong&gt; &lt;a href="https://cxjysvlq.api.sanity.io/v2025-08-15/data/query/production?query=%2A%5B_type%20in%20%5B%22source%22%2C%22marketEvent%22%2C%22evidenceClaim%22%5D%5D%5B0...20%5D%7B_id%2C_type%2Ctitle%7D" rel="noopener noreferrer"&gt;Query published source, question, and claim records&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosted Sanity Studio:&lt;/strong&gt; &lt;a href="https://phoniex-market-evidence-desk.sanity.studio/" rel="noopener noreferrer"&gt;phoniex-market-evidence-desk.sanity.studio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sourcebook Knowledge Base ID:&lt;/strong&gt; &lt;code&gt;kbu9WNgZ9ocF&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Knowledge Base is a selected index, while the public graph contains the published research records. Their counts can differ. Publishing a dataset change also does not, by itself, prove that a previously built Sourcebook entry has incorporated it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Session and Evaluation
&lt;/h2&gt;

&lt;p&gt;I saved a &lt;a href="https://github.com/PHONIEXz/market-evidence-desk/blob/main/agent-sessions/2026-09-30-public-session.md" rel="noopener noreferrer"&gt;public ten-question agent session&lt;/a&gt; with returned answers, reported Sanity Context tool calls, and criteria used to check each response. Eight questions passed the first run. Two failed, including a service error that I counted as a failure.&lt;/p&gt;

&lt;p&gt;After changes to retries and source validation, I &lt;a href="https://github.com/PHONIEXz/market-evidence-desk/blob/main/agent-sessions/2026-09-30-retest.md" rel="noopener noreferrer"&gt;reran the same ten questions&lt;/a&gt;. All ten returned HTTP 200 on the first call and passed those original core criteria. This is a small recorded test, not a promise that an external model service will never fail.&lt;/p&gt;

&lt;p&gt;The tests include source comparison, the SEC staff and Commissioner disagreement, and a live Bitcoin price and buy-advice question that the historical evidence cannot answer.&lt;/p&gt;

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

&lt;p&gt;The difficult part was preserving the limits of each source. A dated investor alert, a company’s explanation, an international recommendation, and a Commissioner’s statement do not carry the same authority or answer the same question.&lt;/p&gt;

&lt;p&gt;Sanity let me keep those distinctions in the content itself: separate records, explicit references, dates, stances, source locations, and review fields. Sanity Context then gave the agent a way to retrieve that structure and the Sourcebook context before writing.&lt;/p&gt;

&lt;p&gt;The result is a research draft whose claims a reader can trace back to the original publications, challenge, and revise. Market Evidence Desk remains a historical evidence tool. It has no live price feed and does not issue trading decisions. Its AI answers are drafts for readers to check against the receipts.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>sanitychallenge</category>
      <category>sanity</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
