<?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: Sandeep Chakravartty</title>
    <description>The latest articles on DEV Community by Sandeep Chakravartty (@sandeep_chakravartty_219e).</description>
    <link>https://dev.to/sandeep_chakravartty_219e</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%2F3984720%2F3da80da8-4d4f-49b3-b594-532dfcf9319e.jpg</url>
      <title>DEV Community: Sandeep Chakravartty</title>
      <link>https://dev.to/sandeep_chakravartty_219e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sandeep_chakravartty_219e"/>
    <language>en</language>
    <item>
      <title>A Skill Is More Than a Markdown File: Vetting scaffold-docs Against OWASP’s Agentic Skills Top 10</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Tue, 27 Oct 2026 17:51:55 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/a-skill-is-more-than-a-markdown-file-vetting-scaffold-docs-against-owasps-agentic-skills-top-10-13d5</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/a-skill-is-more-than-a-markdown-file-vetting-scaffold-docs-against-owasps-agentic-skills-top-10-13d5</guid>
      <description>&lt;p&gt;A documentation skill sounds like a low-risk addition to an AI agent. It reads code, proposes an outline, and helps write documentation.&lt;/p&gt;

&lt;p&gt;But those activities cross security boundaries. The skill reads repository content that someone else may control, carries context between sessions, and asks an agent to write files. Its safety depends on both its instructions and the permissions available to the agent.&lt;/p&gt;

&lt;p&gt;We evaluated &lt;a href="https://github.com/dbreunig/scaffold-docs-skill" rel="noopener noreferrer"&gt;scaffold-docs&lt;/a&gt;, an existing documentation-writing skill, against the &lt;strong&gt;OWASP Agentic Skills Top 10&lt;/strong&gt;. We then implemented a limited set of improvements and checked whether its original workflow still worked.&lt;/p&gt;

&lt;p&gt;The most useful finding was not a hidden malicious command. It was how easily ordinary workflow instructions can leave trust, permissions, and completion state underspecified.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we reviewed
&lt;/h2&gt;

&lt;p&gt;The skill organizes documentation into three sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Getting Started:&lt;/strong&gt; a representative tutorial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diving Deeper:&lt;/strong&gt; explanations of concepts and design decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference:&lt;/strong&gt; API documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its workflow is deliberately iterative. The user selects an audience, reviews the structure, and approves successive drafting passes. An update mode uses stored metadata to reconcile documentation after code changes.&lt;/p&gt;

&lt;p&gt;We pinned the review to commit &lt;code&gt;e234e13eb1ab9561a1da9a5a150c3deee3c515b8&lt;/code&gt;. That matters: a security assessment applies to the content reviewed, not automatically to whatever appears on the default branch tomorrow.&lt;/p&gt;

&lt;p&gt;We also pinned the OWASP reference material and used its &lt;strong&gt;AST01–AST10&lt;/strong&gt; categories. This is the Agentic &lt;strong&gt;Skills&lt;/strong&gt; Top 10, distinct from OWASP’s Agentic Applications taxonomy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start by treating the skill as evidence
&lt;/h2&gt;

&lt;p&gt;We cloned the repositories into an isolated cloud workspace and inspected the target without installing it as an active skill.&lt;/p&gt;

&lt;p&gt;That distinction was essential. A file under review may contain instructions addressed to an agent. Those instructions are evidence to analyze, not authorization to follow.&lt;/p&gt;

&lt;p&gt;The review covered all 15 tracked files, including hidden metadata, phase instructions, bundled references, and historical implementation plans. We recorded file hashes and inspected file types and instruction content.&lt;/p&gt;

&lt;p&gt;No intentionally malicious payload was identified in that snapshot. There were no bundled executable scripts or required remote instruction fetches.&lt;/p&gt;

&lt;p&gt;That was a useful observation, but it was not a safety verdict. Natural-language instructions can still influence an agent’s actions without shipping executable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use OWASP as a set of questions
&lt;/h2&gt;

&lt;p&gt;We mapped the skill against all ten categories:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OWASP category&lt;/th&gt;
&lt;th&gt;Main question&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AST01 — Malicious Skills&lt;/td&gt;
&lt;td&gt;Does the package contain deceptive or harmful instructions?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST02 — Supply Chain Compromise&lt;/td&gt;
&lt;td&gt;Can users identify and verify the content they install?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST03 — Over-Privileged Skills&lt;/td&gt;
&lt;td&gt;What access does the workflow need, and what access could it inherit?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST04 — Insecure Metadata&lt;/td&gt;
&lt;td&gt;Are persisted values validated before influencing behavior?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST05 — Untrusted External Instructions&lt;/td&gt;
&lt;td&gt;Can source material become agent authority?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST06 — Weak Isolation&lt;/td&gt;
&lt;td&gt;Which boundaries does the host actually enforce?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST07 — Update Drift&lt;/td&gt;
&lt;td&gt;Can reviewed content change without another review?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST08 — Poor Scanning&lt;/td&gt;
&lt;td&gt;Does validation examine prose and behavior as well as code?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST09 — No Governance&lt;/td&gt;
&lt;td&gt;Are installation, ownership, approval, and revocation accounted for?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AST10 — Cross-Platform Reuse&lt;/td&gt;
&lt;td&gt;Would another host preserve the same security properties?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The framework helped organize the investigation. It did not turn every missing feature into a confirmed vulnerability.&lt;/p&gt;

&lt;p&gt;For example, the absence of a permission manifest does not prove that a particular host grants excessive access. It means the deployment needs closer examination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate observations from exploit claims
&lt;/h2&gt;

&lt;p&gt;We combined manual instruction review with small, disposable fixtures.&lt;/p&gt;

&lt;p&gt;One fixture tested the update workflow’s documented comparison:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &amp;lt;baseline&amp;gt;..HEAD &lt;span class="nt"&gt;--stat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After modifying a tracked source file and adding an untracked API file, that comparison remained empty because neither change had been committed.&lt;/p&gt;

&lt;p&gt;The command behaved correctly. The workflow’s scope was the problem: it did not clearly state whether it documented committed source or the current working tree.&lt;/p&gt;

&lt;p&gt;Another fixture showed that a documentation filename could resolve through a symlink outside the intended directory. We did not write through that link.&lt;/p&gt;

&lt;p&gt;These findings support different conclusions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Git comparison demonstrably omits working-tree changes.&lt;/li&gt;
&lt;li&gt;The symlink fixture demonstrates a containment precondition.&lt;/li&gt;
&lt;li&gt;Neither test proves that an agent would perform an unauthorized write or escape its host sandbox.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That distinction keeps a security report actionable without overstating its evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be precise about isolation
&lt;/h2&gt;

&lt;p&gt;The assessment ran in an isolated cloud task, but network access remained enabled for retrieving source material.&lt;/p&gt;

&lt;p&gt;We also attempted a stronger nested Bubblewrap sandbox with network isolation. It failed during UID-map setup, before the child command ran.&lt;/p&gt;

&lt;p&gt;We continued with static review and harmless local fixtures. We did not describe the assessment as air-gapped or claim that the additional sandbox boundary worked.&lt;/p&gt;

&lt;p&gt;A useful rule emerged: &lt;strong&gt;report the boundary you verified, not the boundary you intended to create.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The biggest gaps were in trust and state
&lt;/h2&gt;

&lt;p&gt;The review identified several improvement areas.&lt;/p&gt;

&lt;p&gt;First, the skill asked the agent to read comments, examples, existing documentation, and audience metadata without explicitly separating those inputs from instructions that could authorize actions.&lt;/p&gt;

&lt;p&gt;A stored audience description should influence tone and depth. It should not be able to grant tool permissions or skip a checkpoint.&lt;/p&gt;

&lt;p&gt;Second, file-access scope was undefined. Relative output names did not establish where writes were permitted, and editorial checkpoints did not enforce filesystem containment.&lt;/p&gt;

&lt;p&gt;Third, installation guidance allowed copying or symlinking the skill directory without a package-wide integrity procedure. A reviewed skill can drift if its installed resources change.&lt;/p&gt;

&lt;p&gt;Finally, synchronization metadata needed a clearer lifecycle. Further evaluation found that the creation workflow recorded a “last synced” commit during planning—before the documentation was complete.&lt;/p&gt;

&lt;p&gt;An interrupted session could therefore leave behind a convincing-looking sync marker for unfinished work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implement a focused set of changes
&lt;/h2&gt;

&lt;p&gt;We limited implementation to four recommendation groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;R1:&lt;/strong&gt; explicit instruction/data boundaries and trusted approval recovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;R3:&lt;/strong&gt; separate in-progress work from completed synchronization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;R4:&lt;/strong&gt; validate metadata and use a stable, explicit source revision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;R7:&lt;/strong&gt; resolve audience precedence and non-Git behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The modified workflow now keeps documentation in progress until the selected buckets are complete or explicitly excluded. Updates retain the previous completed baseline while new work is pending.&lt;/p&gt;

&lt;p&gt;Git mode documents a captured committed snapshot. Dirty and untracked source is disclosed as excluded, and source reads use the captured commit consistently.&lt;/p&gt;

&lt;p&gt;Audience handling also became deterministic: an existing audience remains active even when the user has disabled further audience prompts.&lt;/p&gt;

&lt;p&gt;We explicitly left &lt;strong&gt;R2, R5, R6, and R8 unimplemented&lt;/strong&gt;. Those cover broader filesystem enforcement, installation integrity, adversarial regression infrastructure, and runtime support or governance. Adding instructions does not complete those controls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functional validation caught a regression
&lt;/h2&gt;

&lt;p&gt;Security improvements can break normal workflows.&lt;/p&gt;

&lt;p&gt;During validation, we found that phase-entry checks rejected a completed record whenever HEAD had advanced. But a new commit is exactly what normally triggers a documentation update.&lt;/p&gt;

&lt;p&gt;We corrected the distinction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State validation permits a completed record to reference the previous target.&lt;/li&gt;
&lt;li&gt;Starting an update captures the new target.&lt;/li&gt;
&lt;li&gt;Active source reads and completion still reject an unexpected HEAD change during the session.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After that correction, &lt;strong&gt;30 checks passed&lt;/strong&gt;. They covered state transitions, committed-source reads, interrupted work, updates, non-Git completion, and preservation of the original editorial instructions.&lt;/p&gt;

&lt;p&gt;The original prose, headline, audience, and topic-selection references remained unchanged. The drafting passes and review checkpoints were preserved.&lt;/p&gt;

&lt;p&gt;These were deterministic checks with simulated documents and approval outcomes. They did not establish end-to-end writing quality, real human-review behavior, or universal resistance to prompt injection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons for skill authors and reviewers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Review prose as part of the attack surface.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A Markdown-only package can still direct consequential tool use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep editorial preferences separate from authority.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Audience descriptions, comments, and prior documents should guide content—not permissions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model completion honestly.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
“Planning started,” “draft approved,” and “documentation synchronized” are different states.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose a source boundary and use it consistently.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Comparing committed changes while reading uncommitted files produces an ambiguous result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distinguish skill guidance from host enforcement.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A rule against writing outside a directory is useful. A host that denies the write provides a stronger boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test the ordinary path after hardening.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The update-entry regression was found through functional validation, not through searching for malicious payloads.&lt;/p&gt;

&lt;p&gt;The resulting &lt;a href="https://github.com/scha54/scaffold-doc-skills-vetting" rel="noopener noreferrer"&gt;vetting repository&lt;/a&gt; contains the original assessment, recommendations, scoped implementation, and validation evidence. Its findings describe what was observed, what was changed, and what still needs testing—the distinctions a useful skill-security review should preserve.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>webdev</category>
      <category>owasp</category>
    </item>
    <item>
      <title>SlothMode: A Quest Generator That Gives You Permission to Do Less</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Mon, 26 Oct 2026 00:15:08 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/slothmode-a-quest-generator-that-gives-you-permission-to-do-less-49ap</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/slothmode-a-quest-generator-that-gives-you-permission-to-do-less-49ap</guid>
      <description>&lt;p&gt;This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;br&gt;
What I Built&lt;br&gt;
SlothMode turns a few choices—your energy, mood, available time, location, and constraints—into a tiny, playful quest. You can accept it, reroll it, mark it “Done-ish,” or choose to do nothing. There are no streaks or deadlines. Even intentional rest earns fictional points.&lt;/p&gt;

&lt;p&gt;The app saves your preferences and adventures in your browser. You can export your history as JSON or download a personalized PNG certificate. No account is needed.&lt;br&gt;
Demo&lt;br&gt;
There isn’t a deployed demo or video yet. You can run the handcrafted demo locally without installing a model:&lt;br&gt;
git clone &lt;a href="https://github.com/scha54/SlothMode.git" rel="noopener noreferrer"&gt;https://github.com/scha54/SlothMode.git&lt;/a&gt;&lt;br&gt;
cd SlothMode&lt;br&gt;
npm ci&lt;br&gt;
npm run dev&lt;br&gt;
Open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, select Demo · handcrafted quests, and click Find My Perfect Nothing. These quests are clearly labeled as handcrafted; they are not AI-generated.&lt;/p&gt;

&lt;p&gt;Desktop screenshot · Mobile screenshot · Example certificate&lt;br&gt;
Code&lt;br&gt;
The source, setup instructions, tests, and architecture notes are in the SlothMode GitHub repository.&lt;/p&gt;

&lt;p&gt;The central AI boundary is deliberately small. The model selects values for a versioned activity plan:&lt;br&gt;
const activityPlanSchema = z.object({&lt;br&gt;
  version: z.literal(1),&lt;br&gt;
  activity: z.enum(["imagine", "remember", "observe", "rest"]),&lt;br&gt;
  subject: z.enum([/* 16 reviewed subjects &lt;em&gt;/]),&lt;br&gt;
  setting: z.enum([/&lt;/em&gt; 12 reviewed settings &lt;em&gt;/]),&lt;br&gt;
  twist: z.enum([/&lt;/em&gt; 12 reviewed twists */]),&lt;br&gt;
}).strict();&lt;br&gt;
Application code turns that plan into the words the user sees. The model cannot supply unrestricted instructions. If its response fails validation, SlothMode reports an error instead of quietly passing off a handcrafted quest as AI output.&lt;br&gt;
How I Built It&lt;br&gt;
SlothMode uses Next.js, React, TypeScript, Zod, and Dexie. IndexedDB stores preferences, quest history, rewards, and certificate details locally in the browser. The interface includes keyboard controls, reduced-motion support, and an original animated SVG sloth.&lt;/p&gt;

&lt;p&gt;For local AI, the server adapter targets Gemma 3 4B through Ollama. It sends the user’s preferences and recent quest titles to Ollama’s structured JSON chat endpoint. The response must match the activity-plan schema before the app compiles it into a quest. The separate handcrafted catalog keeps the demo usable when Ollama is unavailable.&lt;/p&gt;

&lt;p&gt;The default model’s manifest digest is pinned, but a full model download and live Gemma inference have not yet been validated. The completed checks cover the app and handcrafted demo: 33 unit tests, nine production browser tests, a production build, and a demo API smoke test. They establish that the demo workflow works; they do not establish live AI output quality or latency.&lt;br&gt;
Why Does Open Innovation Matter?&lt;br&gt;
A local, open-weight model lets this project explore playful generation without requiring users to create an API account or send their preferences to a hosted model provider. The model, prompt, output schema, and validation code are inspectable and changeable. Someone can run the app locally, swap in a compatible model, or improve the activity vocabulary.&lt;/p&gt;

&lt;p&gt;That openness also makes the limits visible. The current AI design is intended for local use; it should not be presented as a working Vercel AI deployment. For now, the reliable public-facing path is the clearly labeled handcrafted demo, while the open-source code provides a foundation for testing and improving local inference.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building Climate Court: Evidence-First Climate Investigations with Next.js, Optional AI, and Verifiable Reports</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Sat, 24 Oct 2026 09:46:57 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/building-climate-court-evidence-first-climate-investigations-with-nextjs-optional-ai-and-2cma</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/building-climate-court-evidence-first-climate-investigations-with-nextjs-optional-ai-and-2cma</guid>
      <description>&lt;p&gt;&lt;em&gt;How we built a local-first investigation platform—and why the most valuable improvements came from testing what happens when things go wrong.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Corporate sustainability claims often sound precise:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“We reduced our carbon emissions by 40%.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But precision in wording does not necessarily mean precision in evidence.&lt;/p&gt;

&lt;p&gt;Reduced compared with which year? Does the figure describe absolute emissions or emissions intensity? Which operations are included? What happened to supply-chain emissions?&lt;/p&gt;

&lt;p&gt;Climate Court was built to make those questions visible.&lt;/p&gt;

&lt;p&gt;The application helps users organize a climate claim into assertions, inspect supporting material, identify evidence gaps, and produce a transparent report. A finalized report can then be fingerprinted and registered on a local blockchain for independent integrity verification.&lt;/p&gt;

&lt;p&gt;The central design principle is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every finding should point to evidence—or explain what evidence is missing.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Climate Court Actually Does
&lt;/h2&gt;

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

&lt;ol&gt;
&lt;li&gt;Submit a climate-related claim.&lt;/li&gt;
&lt;li&gt;Add pasted source material or a text-based PDF.&lt;/li&gt;
&lt;li&gt;Extract atomic assertions and identify ambiguities.&lt;/li&gt;
&lt;li&gt;Inspect evidence classifications, passages, and provenance.&lt;/li&gt;
&lt;li&gt;Generate and finalize a versioned report.&lt;/li&gt;
&lt;li&gt;Register its snapshot hash on a local EVM.&lt;/li&gt;
&lt;li&gt;Recompute the hash and compare it with the registered record.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The application includes a dashboard, investigation workspace, printable reports, JSON exports, version history, audit explorer, and demo controls.&lt;/p&gt;

&lt;p&gt;It runs locally without paid API keys or cloud accounts.&lt;/p&gt;

&lt;p&gt;That independence matters. An investigation should remain usable when an optional model is unavailable, a quota is exhausted, or the local blockchain is offline.&lt;/p&gt;

&lt;p&gt;There is also an important boundary: user-provided documents are not automatically authenticated. They remain inconclusive pending independent review. Clearly labeled synthetic fixtures demonstrate supporting and contradictory classifications without implying that the platform has independently verified real companies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technology Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Interface&lt;/td&gt;
&lt;td&gt;Next.js App Router, React, TypeScript, Tailwind CSS, Lucide&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP backend&lt;/td&gt;
&lt;td&gt;Next.js server-side route handlers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime validation&lt;/td&gt;
&lt;td&gt;Zod&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local persistence&lt;/td&gt;
&lt;td&gt;Schema-validated JSON with atomic replacement and backups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optional cloud persistence&lt;/td&gt;
&lt;td&gt;Supabase PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optional AI&lt;/td&gt;
&lt;td&gt;Official Gemini SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Report integrity&lt;/td&gt;
&lt;td&gt;Canonical serialization and SHA-256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blockchain&lt;/td&gt;
&lt;td&gt;Solidity, Hardhat, Ethers.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automated testing&lt;/td&gt;
&lt;td&gt;Node’s test runner, tsx, Playwright, Chromium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Release checks&lt;/td&gt;
&lt;td&gt;GitHub Actions, secret scanning, dependency auditing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We kept the application as a monolith. The challenge did not require independently deployed services; it required clear boundaries and predictable failure behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: A Small Monolith with Explicit Responsibilities
&lt;/h2&gt;

&lt;p&gt;The architecture separates presentation, orchestration, business rules, persistence, and external adapters.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    User[Presenter or authenticated operator]
    Gateway[Access boundary]
    UI[React workspace]
    API[Validated API routes]
    Cases[Case services]
    Engine[Deterministic assessment engine]
    Store[Repository adapter]
    Audit[Audit service and reconciliation]
    PDF[Bounded PDF child process]
    AI[Optional Gemini adapter]

    User --&amp;gt; Gateway --&amp;gt; UI --&amp;gt; API
    API --&amp;gt; Cases
    Cases --&amp;gt; Engine
    Cases --&amp;gt; Store
    Cases -.-&amp;gt; AI
    API --&amp;gt; PDF
    API --&amp;gt; Audit
    Audit --&amp;gt; Store
    Audit --&amp;gt; EVM[Local Solidity registry]
    Store --&amp;gt; Local[(Local JSON)]
    Store -.-&amp;gt; Cloud[(Optional Supabase)]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The main modules reflect those responsibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lib/engine.ts&lt;/code&gt; handles extraction, assessment, deduplication, and snapshots.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/services.ts&lt;/code&gt; orchestrates case operations and audit state transitions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/store.ts&lt;/code&gt; handles persistence.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/chain.ts&lt;/code&gt; communicates with the registry.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/ai.ts&lt;/code&gt; provides optional interpretation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/readiness.ts&lt;/code&gt; checks required dependencies.&lt;/li&gt;
&lt;li&gt;Dedicated report, presentation, and API-client modules support the interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure made it possible to improve reliability without replacing the framework or introducing a message broker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deterministic Assessment Before AI Interpretation
&lt;/h2&gt;

&lt;p&gt;Climate Court’s core assessment does not depend on an LLM.&lt;/p&gt;

&lt;p&gt;Deterministic extraction identifies explicit quantities, units, reporting years, and qualifiers. It preserves unresolved questions rather than supplying missing context.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;“Our emissions fell 40% last year.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The platform can extract the percentage while leaving the reporting period unresolved. It should not silently decide which year “last year” refers to.&lt;/p&gt;

&lt;p&gt;The assessment uses these verdict labels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SUPPORTED
PARTIALLY_SUPPORTED
CONTRADICTED
INSUFFICIENT_EVIDENCE
UNRESOLVED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current demo conservatively reserves &lt;code&gt;SUPPORTED&lt;/code&gt; for independently complete reviewed evidence rather than issuing it automatically.&lt;/p&gt;

&lt;p&gt;Evidence coverage is separate from the verdict. It counts completed checks, including source availability, reporting periods, comparable measurements, and independent scope verification.&lt;/p&gt;

&lt;p&gt;It is &lt;strong&gt;not a probability that the claim is true&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AI adapter has a narrow role
&lt;/h3&gt;

&lt;p&gt;When configured, Gemini suggests ambiguities. It does not decide the verdict, invent sources, execute tools, or submit transactions.&lt;/p&gt;

&lt;p&gt;The adapter uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A server-side API key.&lt;/li&gt;
&lt;li&gt;A configured model rather than an assumed default.&lt;/li&gt;
&lt;li&gt;Runtime validation of structured JSON.&lt;/li&gt;
&lt;li&gt;Output and token limits.&lt;/li&gt;
&lt;li&gt;Bounded attempts within an overall time budget.&lt;/li&gt;
&lt;li&gt;Deterministic fallback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The effective mode and fallback reason are recorded with the investigation. A “configured” integration flag alone cannot establish that a model successfully ran.&lt;/p&gt;

&lt;p&gt;Live Gemini behavior was not part of the completed local validation, so the application does not claim otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evidence Integrity Starts Before Blockchain
&lt;/h2&gt;

&lt;p&gt;One of the most instructive defects appeared in deduplication.&lt;/p&gt;

&lt;p&gt;An early normalization step removed punctuation. That made these passages appear identical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Emissions were 1.2 tonnes.
Emissions were 12 tonnes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Case folding introduced another scientific problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Energy use was 1 MWh.
Energy use was 1 mWh.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those units are different.&lt;/p&gt;

&lt;p&gt;The corrected implementation deliberately uses conservative, exact text deduplication. It normalizes Unicode and whitespace while preserving case, punctuation, signs, units, and negation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;excerpt&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NFC&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="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &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="nf"&gt;trim&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;Similar passages remain separate. The application no longer claims semantic near-duplicate detection.&lt;/p&gt;

&lt;p&gt;This was a useful architectural lesson: normalization is a domain decision. A transformation that helps ordinary text matching can destroy scientific meaning.&lt;/p&gt;

&lt;p&gt;We also corrected synthetic source passages so their classification explanations refer to details actually present in the excerpt. A synthetic label is disclosure, not a substitute for traceability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Persistence: Simple Storage, Explicit Constraints
&lt;/h2&gt;

&lt;p&gt;For the local demonstration, we chose a JSON repository rather than introducing a database server.&lt;/p&gt;

&lt;p&gt;That keeps setup accessible, but it requires clear limits.&lt;/p&gt;

&lt;p&gt;The local adapter now provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runtime schema validation.&lt;/li&gt;
&lt;li&gt;Aggregate and record-count limits.&lt;/li&gt;
&lt;li&gt;Atomic file replacement.&lt;/li&gt;
&lt;li&gt;File synchronization before replacement.&lt;/li&gt;
&lt;li&gt;A previous validated backup.&lt;/li&gt;
&lt;li&gt;A process-owner writer guard.&lt;/li&gt;
&lt;li&gt;Checksum-verified backup and restore commands.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finalized snapshots are copied separately from working case data. Later evidence additions do not rewrite those snapshots.&lt;/p&gt;

&lt;p&gt;This is application-level immutability, not write-once storage. An actor with filesystem access can still alter files; independent hash verification is what makes changes detectable.&lt;/p&gt;

&lt;p&gt;The optional Supabase adapter uses revision-based compare-and-swap updates to reject lost-update races. That implementation still requires separate validation with a live Supabase environment.&lt;/p&gt;

&lt;p&gt;The lesson was not that JSON is universally sufficient. It was that a small demo benefits from a storage model whose constraints are explicit and tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blockchain Auditing: Two Systems, One Difficult Failure Boundary
&lt;/h2&gt;

&lt;p&gt;The Solidity registry stores minimal information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An opaque case identifier.&lt;/li&gt;
&lt;li&gt;A report version.&lt;/li&gt;
&lt;li&gt;A 32-byte snapshot digest.&lt;/li&gt;
&lt;li&gt;A registration timestamp.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documents and full reports remain off-chain.&lt;/p&gt;

&lt;p&gt;The contract restricts registration to its operator and rejects duplicate case versions and invalid inputs.&lt;/p&gt;

&lt;p&gt;Before registration, the application serializes a finalized snapshot using application-defined canonicalization rules and calculates SHA-256 over the UTF-8 result.&lt;/p&gt;

&lt;p&gt;Verification retrieves the actual registry record, recreates the snapshot digest, and compares them.&lt;/p&gt;

&lt;p&gt;A matching result establishes integrity against that record. It does not establish that the evidence is authentic or the climate claim is correct.&lt;/p&gt;

&lt;h3&gt;
  
  
  The failure we initially missed
&lt;/h3&gt;

&lt;p&gt;The difficult sequence was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transaction confirms on-chain
          ↓
Saving its local metadata fails
          ↓
User retries
          ↓
Contract rejects duplicate registration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both individual systems behaved as designed. The combined workflow did not recover.&lt;/p&gt;

&lt;p&gt;We fixed this with persisted operation states and reconciliation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PENDING → BROADCAST → CONFIRMED
               ↘ UNAVAILABLE
               ↘ STALE
               ↘ CONFLICT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before sending a transaction, the application checks the existing registry record.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An absent record can be registered.&lt;/li&gt;
&lt;li&gt;A matching record can be reconciled with its confirmed receipt.&lt;/li&gt;
&lt;li&gt;A conflicting digest stops the operation.&lt;/li&gt;
&lt;li&gt;Historical metadata without a corresponding current registration is reported as stale or unavailable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This also fixed another misleading behavior: after a chain reset, cached local metadata could previously produce a success response.&lt;/p&gt;

&lt;p&gt;The corrected system checks the chain instead of treating its cache as proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reliability: Keep External Waits Outside Storage Locks
&lt;/h2&gt;

&lt;p&gt;The original mutation queue included network work.&lt;/p&gt;

&lt;p&gt;That meant a stalled blockchain confirmation could delay unrelated case updates.&lt;/p&gt;

&lt;p&gt;The revised approach keeps storage critical sections short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Persist operation intent
          ↓
Release storage queue
          ↓
Perform bounded external work
          ↓
Re-enter queue
          ↓
Merge result into the intended version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Investigation updates use revision checks to avoid overwriting newer edits. Audit results are merged into the specific finalized version they belong to.&lt;/p&gt;

&lt;p&gt;We tested this by pausing local mining. Anchoring reached its deadline while another case could still be finalized.&lt;/p&gt;

&lt;p&gt;The important distinction is that a per-request RPC timeout is not an end-to-end operation deadline. The complete operation needs its own budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security: Protect the Authority Behind the API
&lt;/h2&gt;

&lt;p&gt;Keeping keys off the frontend was necessary, but insufficient.&lt;/p&gt;

&lt;p&gt;The API can invoke an authorized registry operator. Without access control, a reachable client could exercise that authority indirectly.&lt;/p&gt;

&lt;p&gt;Climate Court now has two access modes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local presenter mode
&lt;/h3&gt;

&lt;p&gt;The custom Node server binds to loopback and checks the actual peer, Host header, and original forwarding headers before Next.js handles the request.&lt;/p&gt;

&lt;p&gt;It adds a random process-private gateway proof. Local API access requires that proof and fails closed without it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared operator mode
&lt;/h3&gt;

&lt;p&gt;Shared mode requires HTTPS configuration and securely injected operator credentials. Sessions use signed, expiring cookies with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HttpOnly&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Secure&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SameSite=Strict&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Case reads, reports, mutations, reset controls, and blockchain actions require authorization.&lt;/p&gt;

&lt;p&gt;Additional protections include server-only credential modules, sanitized API errors, secret scanning, staged-content checks, request budgets, and browser security headers.&lt;/p&gt;

&lt;p&gt;PDF extraction runs in a separate process with a bounded heap, page/text limits, a deadline, and no inherited application credentials. This provides resource isolation; it is not an OS security sandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  Readiness, Observability, and Recovery
&lt;/h2&gt;

&lt;p&gt;A health endpoint that always says “ok” is not a readiness check.&lt;/p&gt;

&lt;p&gt;We separated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Liveness:&lt;/strong&gt; the process can answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readiness:&lt;/strong&gt; required configuration, storage, and dependencies are usable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The demo preflight also performs a functional case read and checks the local registry and operator.&lt;/p&gt;

&lt;p&gt;Operational events contain an operation name, request ID, outcome, allowlisted diagnostic code, and duration. Raw SDK errors, credentials, request bodies, and source documents are excluded.&lt;/p&gt;

&lt;p&gt;Recovery is documented and executable. Backup restoration validates the manifest, stored structure, and finalized snapshot digests, while preserving replaced data for inspection.&lt;/p&gt;

&lt;p&gt;Local report backups do not restore ephemeral blockchain history. The runbook makes that distinction explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Architectural Best Practices Helped
&lt;/h2&gt;

&lt;p&gt;We used established frameworks as review lenses rather than claiming formal certification.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Principle&lt;/th&gt;
&lt;th&gt;Concrete application&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS Well-Architected reliability&lt;/td&gt;
&lt;td&gt;Bounded operations, dependency readiness, reconciliation, tested restoration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OWASP access control&lt;/td&gt;
&lt;td&gt;Authorization around report data and operator-backed actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OWASP secrets and error handling&lt;/td&gt;
&lt;td&gt;Server-only modules, secret checks, sanitized public errors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12-Factor configuration&lt;/td&gt;
&lt;td&gt;Runtime configuration and optional backing-service adapters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SOLID separation of concerns&lt;/td&gt;
&lt;td&gt;Independent services, repository boundary, extracted presentation modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google SRE principles&lt;/td&gt;
&lt;td&gt;Failure injection, truthful status, operational budgets, recovery rehearsals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ISO/IEC 25010&lt;/td&gt;
&lt;td&gt;Correctness, recoverability, maintainability, and measured resource behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NIST SSDF&lt;/td&gt;
&lt;td&gt;Repeatable CI gates, dependency review, security regression tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI risk management&lt;/td&gt;
&lt;td&gt;Narrow model authority, explicit uncertainty, provenance, bounded fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The most useful outcome was a prioritized list of small changes. None required an enterprise-scale rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Went Well
&lt;/h2&gt;

&lt;p&gt;The final local validation included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;34 passing automated tests.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;HTTP and desktop/mobile browser workflows.&lt;/li&gt;
&lt;li&gt;Browser upload, retry, and refresh failure paths.&lt;/li&gt;
&lt;li&gt;Real transaction confirmation followed by local persistence failure.&lt;/li&gt;
&lt;li&gt;Chain stalls, resets, and conflicting digests.&lt;/li&gt;
&lt;li&gt;Backup, restore, restart, and operator-access checks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ten consecutive complete claim-to-verification rehearsals.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A bounded local resource rehearsal used 20 load cases, five 1,000-word sources per case, and three snapshots each.&lt;/p&gt;

&lt;p&gt;After warm-up, across 20 measured iterations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Measurement&lt;/th&gt;
&lt;th&gt;Observed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read latency p95&lt;/td&gt;
&lt;td&gt;24 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write latency p95&lt;/td&gt;
&lt;td&gt;54 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Peak RSS&lt;/td&gt;
&lt;td&gt;288 MiB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are local observations, not hosted availability guarantees.&lt;/p&gt;

&lt;p&gt;The production dependency audit reported zero vulnerabilities after patching Zod and PostCSS. A separate full-tree audit still identified development-tool advisories; their applicability and residual risks are documented rather than hidden.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;The happy path is weak evidence of reliability.&lt;/strong&gt; The most valuable tests interrupted the workflow between successful steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retries are part of the architecture.&lt;/strong&gt; An error message cannot compensate for an operation that is unsafe to repeat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Truthful status is a correctness requirement.&lt;/strong&gt; “Configured,” “registered,” “confirmed,” and “verified” describe different facts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scientific text needs conservative processing.&lt;/strong&gt; Decimal points, signs, scope, units, and casing can change the meaning of evidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI availability should not determine application availability.&lt;/strong&gt; A narrow optional adapter made fallback straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A monolith can have strong boundaries.&lt;/strong&gt; Separating responsibilities and shortening critical sections solved the demonstrated problems without multiplying infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;The next useful capability is a human-reviewed evidence classification workflow, with stronger provenance and richer comparisons across reporting periods and emissions scopes.&lt;/p&gt;

&lt;p&gt;Other planned work includes live validation of the optional Gemini and Supabase adapters, authenticated collaboration, and public-testnet integration.&lt;/p&gt;

&lt;p&gt;Those are separate deployment and product scopes. The current evidence supports a controlled local single-operator demonstration—not a claim of public production readiness.&lt;/p&gt;

&lt;p&gt;Climate Court’s goal remains consistent: help users follow the evidence, preserve uncertainty, and make the resulting investigation independently inspectable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/scha54/Climate-Court" rel="noopener noreferrer"&gt;github.com/scha54/Climate-Court&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>typescript</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>From Vibe Coding to Demo-Ready: Hardening a React Application with the Twelve-Factor App Methodology</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Sat, 24 Oct 2026 09:15:49 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/from-vibe-coding-to-demo-ready-hardening-a-react-application-with-the-twelve-factor-app-methodology-3ghe</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/from-vibe-coding-to-demo-ready-hardening-a-react-application-with-the-twelve-factor-app-methodology-3ghe</guid>
      <description>&lt;p&gt;&lt;em&gt;How I used software architecture principles, the Twelve-Factor methodology, security controls, automated testing, and immutable deployments to harden a Rapid Circularity Assessment calculator.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction: The challenge with vibe-coded applications
&lt;/h2&gt;

&lt;p&gt;Vibe coding has fundamentally changed how quickly we can translate ideas into working applications.&lt;/p&gt;

&lt;p&gt;With AI-assisted development, we can move from a concept to a functioning prototype in hours rather than weeks. This is particularly valuable for experimentation, research applications, proof-of-concepts, and demonstrations.&lt;/p&gt;

&lt;p&gt;However, there is a significant difference between an application that &lt;em&gt;works on a developer's machine&lt;/em&gt; and one that is sufficiently reliable, secure, explainable, and reproducible for a professional demonstration.&lt;/p&gt;

&lt;p&gt;AI-generated applications may work well along their intended happy paths but still have architectural weaknesses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited separation of business logic and presentation&lt;/li&gt;
&lt;li&gt;Unvalidated user inputs and browser storage&lt;/li&gt;
&lt;li&gt;Inconsistent error handling&lt;/li&gt;
&lt;li&gt;Uncontrolled dependencies&lt;/li&gt;
&lt;li&gt;Missing automated testing&lt;/li&gt;
&lt;li&gt;Environment-specific assumptions&lt;/li&gt;
&lt;li&gt;Limited operational observability&lt;/li&gt;
&lt;li&gt;Unrepeatable build and deployment processes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These weaknesses become particularly visible during demonstrations, when an unexpected input, browser refresh, deployment issue, or calculation inconsistency can undermine the credibility of the entire solution.&lt;/p&gt;

&lt;p&gt;I encountered this engineering challenge while developing the &lt;strong&gt;Rapid Circularity Assessment (RCA) Calculator&lt;/strong&gt;, a browser-based application for estimating material savings and additional environmental and worker outcomes associated with circular business models.&lt;/p&gt;

&lt;p&gt;Rather than introducing an unnecessarily complex enterprise architecture, I used the &lt;strong&gt;Twelve-Factor App methodology as an architectural hardening framework&lt;/strong&gt;, supplemented by security engineering, automated testing, deployment verification, and operational readiness practices.&lt;/p&gt;

&lt;p&gt;This article explains the application architecture, the technology stack, the hardening decisions, and how the twelve factors were adapted to a predominantly client-side system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub repository:&lt;/strong&gt; &lt;a href="https://github.com/scha54/RCA-Calculator" rel="noopener noreferrer"&gt;https://github.com/scha54/RCA-Calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live application:&lt;/strong&gt; &lt;a href="https://rca-calculator.vercel.app" rel="noopener noreferrer"&gt;https://rca-calculator.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Understanding the RCA Calculator
&lt;/h2&gt;

&lt;p&gt;The RCA Calculator is a research-oriented screening application designed to explore how circular economy interventions might reduce virgin textile consumption.&lt;/p&gt;

&lt;p&gt;Users can model interventions such as extending product lifetimes, increasing garment reuse, improving textile collection and recycling, and reducing manufacturing waste.&lt;/p&gt;

&lt;p&gt;The application provides the ability to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estimate annual virgin textile material savings.&lt;/li&gt;
&lt;li&gt;Compare up to three assessment scenarios.&lt;/li&gt;
&lt;li&gt;Evaluate material circularity across slowing, closing, and life-cycle strategies.&lt;/li&gt;
&lt;li&gt;Explore environmental and worker-related outcomes.&lt;/li&gt;
&lt;li&gt;Apply configurable uncertainty assumptions.&lt;/li&gt;
&lt;li&gt;Conduct sensitivity analysis to identify influential parameters.&lt;/li&gt;
&lt;li&gt;Visualize results through radar charts and sensitivity diagrams.&lt;/li&gt;
&lt;li&gt;Export assessment results to Excel, JSON, Markdown, and printable reports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An important characteristic of this application is that &lt;strong&gt;it is a screening model, not a certified Life Cycle Assessment (LCA) system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The calculations support exploratory evaluation and decision-making. They do not establish independently audited environmental impact claims.&lt;/p&gt;

&lt;p&gt;This distinction influenced the architecture. The application needed transparent calculations, explicit assumptions, validation, and traceable outputs rather than a complicated backend infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Architecture: A modular, browser-first application
&lt;/h2&gt;

&lt;p&gt;The deployed RCA Calculator follows a &lt;strong&gt;static-client, modular frontend architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It does not require an application backend, shared database, authentication service, or server-side calculation engine.&lt;/p&gt;

&lt;p&gt;Instead, the system separates presentation, domain calculations, scenario management, local persistence, reporting, and deployment responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-level architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  User / Browser
                         |
                         v
                React Presentation
                         |
           +-------------+-------------+
           |             |             |
           v             v             v
      Assessment     Scenario       Results and
      Workflow       Management     Visualization
           |             |             |
           +-------------+-------------+
                         |
                         v
                TypeScript Domain
                 Calculation Engine
                         |
          +--------------+-------------+
          |              |             |
          v              v             v
     JSON Model      Sensitivity    Additional
     Definitions      Analysis       Outcomes
          |              |             |
          +--------------+-------------+
                         |
              +----------+----------+
              |                     |
              v                     v
       Browser Storage        Export Services
        (localStorage)      JSON / Excel / Print
              |
              v
        Portable Backup


              Delivery Architecture

          GitHub Source Repository
                    |
                    v
             GitHub Actions
                    |
          +---------+----------+
          |                    |
          v                    v
     Automated Tests     Security &amp;amp; Build
                            Validation
          |                    |
          +---------+----------+
                    |
                    v
             Vite Build
                    |
                    v
           Immutable dist/
           + release.json
                    |
           +--------+---------+
           |                  |
           v                  v
       Vercel CDN       Portable Node
                       Static Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The architecture makes a deliberate trade-off: it prioritizes simplicity, reproducibility, privacy, and maintainability over features that would require centralized application state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separation of architectural responsibilities
&lt;/h3&gt;

&lt;p&gt;The codebase is structured around identifiable functional boundaries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RCA-Calculator/
|
+-- data/
|   +-- formulas.json
|   +-- parameters.json
|   +-- confidence.json
|   +-- benchmarks.json
|   +-- settings.json
|
+-- src/
|   +-- components/
|   +-- pages/
|   +-- engine/
|   |   +-- model.ts
|   |   +-- calculate.ts
|   |   +-- outcomes.ts
|   |
|   +-- export/
|   |   +-- excel.ts
|   |   +-- json.ts
|   |
|   +-- platform/
|   |   +-- diagnostics.ts
|   |
|   +-- App.tsx
|   +-- main.tsx
|
+-- tests/
+-- e2e/
+-- scripts/
+-- docs/
+-- .github/workflows/
|
+-- package.json
+-- package-lock.json
+-- vercel.json
+-- vite.config.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure serves several architectural purposes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Presentation remains separate from calculation logic.&lt;/strong&gt; React components manage user interaction, navigation, and visualization, while domain logic is implemented in TypeScript modules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model definitions are externalized into version-controlled JSON files.&lt;/strong&gt; Parameters, formulas, confidence bands, and reference benchmarks are independently identifiable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Export functionality is isolated.&lt;/strong&gt; Generating an Excel workbook does not require embedding workbook-generation logic inside the assessment screens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform responsibilities are explicit.&lt;/strong&gt; Diagnostics, deployment configuration, build verification, and runtime serving are distinguishable from domain calculations.&lt;/p&gt;

&lt;p&gt;This separation is important when hardening an AI-assisted application because it makes code reviews and automated testing more focused.&lt;/p&gt;

&lt;p&gt;Instead of reviewing a large, tightly coupled component, we can review specific architectural responsibilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Technology stack
&lt;/h2&gt;

&lt;p&gt;The RCA Calculator uses a relatively small but purposeful technology stack.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;UI framework&lt;/td&gt;
&lt;td&gt;React 19&lt;/td&gt;
&lt;td&gt;Component-based interactive interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Programming language&lt;/td&gt;
&lt;td&gt;TypeScript 5.8&lt;/td&gt;
&lt;td&gt;Type safety and maintainable domain logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build system&lt;/td&gt;
&lt;td&gt;Vite 6&lt;/td&gt;
&lt;td&gt;Development tooling and optimized production bundles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Styling&lt;/td&gt;
&lt;td&gt;Tailwind CSS 4&lt;/td&gt;
&lt;td&gt;Responsive presentation and design consistency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visualization&lt;/td&gt;
&lt;td&gt;Recharts 3&lt;/td&gt;
&lt;td&gt;Results and analytical charts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workbook generation&lt;/td&gt;
&lt;td&gt;ExcelJS 4.4&lt;/td&gt;
&lt;td&gt;Client-side Excel report generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence&lt;/td&gt;
&lt;td&gt;Browser localStorage&lt;/td&gt;
&lt;td&gt;Local assessment state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unit testing&lt;/td&gt;
&lt;td&gt;Vitest 5&lt;/td&gt;
&lt;td&gt;Model and utility verification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser testing&lt;/td&gt;
&lt;td&gt;Playwright&lt;/td&gt;
&lt;td&gt;End-to-end workflow verification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessibility testing&lt;/td&gt;
&lt;td&gt;axe-core with Playwright&lt;/td&gt;
&lt;td&gt;Automated accessibility checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime tooling&lt;/td&gt;
&lt;td&gt;Node.js 24 / npm 11&lt;/td&gt;
&lt;td&gt;Reproducible builds and portable serving&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI&lt;/td&gt;
&lt;td&gt;GitHub Actions&lt;/td&gt;
&lt;td&gt;Automated validation and release artifact generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting&lt;/td&gt;
&lt;td&gt;Vercel&lt;/td&gt;
&lt;td&gt;Static application delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Version control&lt;/td&gt;
&lt;td&gt;Git / GitHub&lt;/td&gt;
&lt;td&gt;Source control and release traceability&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Python also appears in the repository as a utility for creating model data. It is not part of the deployed browser runtime.&lt;/p&gt;

&lt;p&gt;An important architectural decision was to avoid introducing technologies without a clear application requirement.&lt;/p&gt;

&lt;p&gt;For example, adding PostgreSQL, Redis, message queues, or Kubernetes would not automatically make this calculator more robust. For the current single-user browser workflow, these technologies would increase operational responsibilities without providing proportional value.&lt;/p&gt;

&lt;p&gt;The architecture follows a practical principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use the minimum system complexity required to satisfy the application's functional and non-functional requirements.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Designing a reliable domain calculation engine
&lt;/h2&gt;

&lt;p&gt;For a scientific screening application, the calculation engine is one of the most important architectural components.&lt;/p&gt;

&lt;p&gt;A visually polished interface is of limited value if the underlying model is inconsistent or cannot be independently verified.&lt;/p&gt;

&lt;p&gt;The RCA Calculator defines model parameters and mathematical expressions separately from the presentation layer.&lt;/p&gt;

&lt;p&gt;The calculation engine reads those definitions, validates scenario inputs, evaluates formulas, and produces structured results.&lt;/p&gt;

&lt;p&gt;For example, the baseline virgin textile demand is calculated as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Baseline Virgin Demand =
    Items Sold
  × Average Garment Weight
  × (1 - Collection Rate × Recycling Yield)
  / 1000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The division converts kilograms into tonnes.&lt;/p&gt;

&lt;p&gt;The application then calculates contributions from several circularity interventions and derives total material savings and residual virgin demand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restricted formula evaluation
&lt;/h3&gt;

&lt;p&gt;One useful hardening decision was implementing a restricted arithmetic parser instead of evaluating expressions as JavaScript.&lt;/p&gt;

&lt;p&gt;The parser accepts a controlled set of operations, numeric literals, named variables, parentheses, and MIN/MAX functions.&lt;/p&gt;

&lt;p&gt;It does not execute arbitrary JavaScript from model definitions or imported scenarios.&lt;/p&gt;

&lt;p&gt;This creates an important security boundary between externally represented calculation data and executable application code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Input and model validation
&lt;/h3&gt;

&lt;p&gt;The domain model also validates incoming scenarios.&lt;/p&gt;

&lt;p&gt;Validation includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scenario schema version and structural integrity&lt;/li&gt;
&lt;li&gt;Supported geographic regions&lt;/li&gt;
&lt;li&gt;Numeric bounds and finite numeric values&lt;/li&gt;
&lt;li&gt;Valid confidence selections&lt;/li&gt;
&lt;li&gt;Consistency of uncertainty bands&lt;/li&gt;
&lt;li&gt;Required model assumptions&lt;/li&gt;
&lt;li&gt;Qualitative checklist and risk-note structures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scenario imports are additionally subject to a 1 MiB size limit before parsing.&lt;/p&gt;

&lt;p&gt;This protects against malformed inputs and reduces the risk of accidental excessive memory consumption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scientific integrity as an architectural quality attribute
&lt;/h3&gt;

&lt;p&gt;A particularly valuable hardening feature is the separation between calculating draft results and authorizing formal report generation.&lt;/p&gt;

&lt;p&gt;Users can explore results while refining assumptions. However, finalized reports require confirmation of material assumptions such as substitution and rebound, along with source information for enabled additional outcome modules.&lt;/p&gt;

&lt;p&gt;Editing relevant model assumptions invalidates those confirmations.&lt;/p&gt;

&lt;p&gt;This is not merely a UI feature.&lt;/p&gt;

&lt;p&gt;It is an example of implementing &lt;strong&gt;domain-specific quality controls directly into the application's architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It helps prevent unreviewed assumptions from silently becoming apparently authoritative outputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Applying the Twelve-Factor App methodology
&lt;/h2&gt;

&lt;p&gt;The Twelve-Factor App methodology was originally developed for software-as-a-service applications, especially systems with server-side processes and backing services.&lt;/p&gt;

&lt;p&gt;It would be inappropriate to apply every factor literally to a static browser application.&lt;/p&gt;

&lt;p&gt;Instead, I used the methodology to assess each architectural concern against the RCA Calculator's actual deployment model.&lt;/p&gt;

&lt;p&gt;The key question was not:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How can this application be made to look like a conventional cloud-native service?&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;How can each applicable Twelve-Factor principle improve the reliability, portability, security, and operational readiness of this application?&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor I — Codebase: One codebase, multiple deployments
&lt;/h3&gt;

&lt;p&gt;The first factor requires one codebase tracked in version control, with multiple deployments derived from it.&lt;/p&gt;

&lt;p&gt;The RCA Calculator uses a single GitHub repository as the source of truth.&lt;/p&gt;

&lt;p&gt;During hardening, unnecessary tracked npm cache content was identified and removed from the Git index. Ignore rules exclude generated output, local environment files, caches, and deployment metadata.&lt;/p&gt;

&lt;p&gt;The intended result is a cleaner source repository where build outputs are generated rather than manually maintained.&lt;/p&gt;

&lt;p&gt;This supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More predictable code reviews&lt;/li&gt;
&lt;li&gt;Cleaner continuous integration&lt;/li&gt;
&lt;li&gt;Release traceability&lt;/li&gt;
&lt;li&gt;Consistent preview and production builds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The existing Git history was not rewritten to eliminate historical cache objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor II — Dependencies: Explicit and reproducible dependency management
&lt;/h3&gt;

&lt;p&gt;A common source of demo failures is inconsistent dependency installation.&lt;/p&gt;

&lt;p&gt;A prototype may work locally because packages were installed incrementally or differ from the versions available in a clean environment.&lt;/p&gt;

&lt;p&gt;The RCA Calculator addresses this using &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;package-lock.json&lt;/code&gt;, a declared Node version, and a recorded npm version.&lt;/p&gt;

&lt;p&gt;The application specifies Node.js 24 and npm 11, with npm 11.9.0 recorded as its package manager.&lt;/p&gt;

&lt;p&gt;A clean installation uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm ci &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike a general dependency update, &lt;code&gt;npm ci&lt;/code&gt; installs from the committed lockfile and rejects incompatible dependency manifests.&lt;/p&gt;

&lt;p&gt;Dependency hygiene was also incorporated into CI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run audit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The audit command fails on high- and critical-severity findings.&lt;/p&gt;

&lt;p&gt;During hardening, unused direct dependencies were removed, and Vitest was upgraded to address serious toolchain advisories.&lt;/p&gt;

&lt;p&gt;One moderate ExcelJS transitive dependency advisory involving UUID remained documented, with its usage and risk boundary explicitly analyzed rather than silently suppressed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Dependency hardening requires reproducibility, inventory, risk assessment, and continuous review—not simply installing the latest versions of everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor III — Config: Separate configuration from code
&lt;/h3&gt;

&lt;p&gt;Twelve-Factor applications should keep deployment-specific configuration outside their source code.&lt;/p&gt;

&lt;p&gt;For the RCA Calculator, there are no backend credentials, database connection strings, or private API keys to configure.&lt;/p&gt;

&lt;p&gt;The browser application is designed to operate without application environment variables.&lt;/p&gt;

&lt;p&gt;The portable Node server supports environment configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000
&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0
&lt;span class="nv"&gt;SHUTDOWN_TIMEOUT_MS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The build also supports revision metadata through environment-provided values such as &lt;code&gt;RELEASE_REVISION&lt;/code&gt; and Vercel's &lt;code&gt;VERCEL_GIT_COMMIT_SHA&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An important distinction is maintained between configuration and domain model data.&lt;/p&gt;

&lt;p&gt;Mathematical formulas and model assumptions belong in version-controlled domain definitions because changing them changes the behavior and interpretation of the assessment.&lt;/p&gt;

&lt;p&gt;They are not interchangeable deployment settings.&lt;/p&gt;

&lt;p&gt;Another important frontend security consideration is that Vite client-side configuration is not secret storage.&lt;/p&gt;

&lt;p&gt;Values embedded into a public JavaScript bundle must be treated as publicly accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor IV — Backing services: Explicit service dependencies
&lt;/h3&gt;

&lt;p&gt;A conventional cloud application may rely on a database, cache, or external message broker.&lt;/p&gt;

&lt;p&gt;The RCA Calculator has no such server-side backing-service dependency.&lt;/p&gt;

&lt;p&gt;Assessment state is stored locally in the user's browser using &lt;code&gt;localStorage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This substantially reduces deployment complexity and avoids introducing a centralized store for user-generated assessment data.&lt;/p&gt;

&lt;p&gt;However, browser storage is not equivalent to a durable, account-backed database.&lt;/p&gt;

&lt;p&gt;Its limitations are explicitly documented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data is associated with a browser and origin.&lt;/li&gt;
&lt;li&gt;Clearing browser storage can delete assessments.&lt;/li&gt;
&lt;li&gt;Assessments do not automatically synchronize between devices.&lt;/li&gt;
&lt;li&gt;Users must export JSON backups when portability is required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is an intentional product constraint, not something that should be hidden behind a claim of database-like durability.&lt;/p&gt;

&lt;p&gt;If collaboration, authentication, or cross-device persistence becomes necessary, a separate backing service would need to be designed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor V — Build, release, run: Immutable deployments
&lt;/h3&gt;

&lt;p&gt;This was one of the most significant parts of the architecture hardening.&lt;/p&gt;

&lt;p&gt;In loosely managed applications, the production server may install dependencies, compile code, or modify files during startup.&lt;/p&gt;

&lt;p&gt;That makes it difficult to know whether the deployed application is identical to what was tested.&lt;/p&gt;

&lt;p&gt;The RCA Calculator separates build, release verification, and runtime serving.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source Code
    |
    v
npm ci
    |
    v
TypeScript Check + Vite Build
    |
    v
dist/
    |
    v
release.json
    |
    v
Integrity Verification
    |
    v
Tested Release Artifact
    |
    v
Deployment / Serving
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The build command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It performs TypeScript checking, builds the application, and generates release metadata.&lt;/p&gt;

&lt;p&gt;The generated &lt;code&gt;release.json&lt;/code&gt; contains information including the application version, source revision, artifact identifier, and SHA-256 checksums of the release files.&lt;/p&gt;

&lt;p&gt;Verification runs with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run check:release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The portable production server verifies the existing artifact before serving it.&lt;/p&gt;

&lt;p&gt;Crucially, the runtime does not rebuild the application.&lt;/p&gt;

&lt;p&gt;This gives deployments a stronger identity: the released files can be checked against the exact artifact that passed validation.&lt;/p&gt;

&lt;p&gt;The checksum manifest is an integrity mechanism, not a digital signature proving the identity of a publisher.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor VI — Processes: Stateless application serving
&lt;/h3&gt;

&lt;p&gt;The deployed serving layer is stateless.&lt;/p&gt;

&lt;p&gt;The Node server serves an immutable directory and does not maintain user assessments, sessions, or mutable application state.&lt;/p&gt;

&lt;p&gt;Calculations and editing occur inside the browser.&lt;/p&gt;

&lt;p&gt;This means multiple serving instances can deliver the same release artifact without synchronizing user sessions.&lt;/p&gt;

&lt;p&gt;The architecture avoids sticky-session requirements and server-side state recovery concerns.&lt;/p&gt;

&lt;p&gt;Browser-local data remains a separate responsibility.&lt;/p&gt;

&lt;p&gt;This is an example of how stateless service architecture can coexist with client-side state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor VII — Port binding: Self-contained runtime behavior
&lt;/h3&gt;

&lt;p&gt;Vercel hosts the static application and manages HTTP delivery.&lt;/p&gt;

&lt;p&gt;For environments requiring a standalone process, the repository also contains a portable Node.js server.&lt;/p&gt;

&lt;p&gt;The server binds to its configured host and port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000 &lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0 npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also exposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /healthz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The health response reports runtime readiness and the current artifact identifier.&lt;/p&gt;

&lt;p&gt;This endpoint is specific to the portable Node server. It is not automatically an application endpoint on the Vercel static deployment.&lt;/p&gt;

&lt;p&gt;For Vercel, the operational documentation recommends using release metadata and live endpoint checks to verify the deployed version.&lt;/p&gt;

&lt;p&gt;The portable server should be placed behind an HTTPS-terminating proxy when exposed to end users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor VIII — Concurrency: Scaling without shared state
&lt;/h3&gt;

&lt;p&gt;The application does not require a distributed calculation cluster.&lt;/p&gt;

&lt;p&gt;Its analytical calculations are performed in each user's browser, while static assets can be distributed through a CDN.&lt;/p&gt;

&lt;p&gt;For standalone hosting, independent Node processes can serve the same immutable build.&lt;/p&gt;

&lt;p&gt;Operational tests exercise multiple server instances using the same release artifact.&lt;/p&gt;

&lt;p&gt;This demonstrates independence of serving instances, but it does not establish a particular requests-per-second capacity or geographic latency guarantee.&lt;/p&gt;

&lt;p&gt;Those require separate load testing and hosting-level measurements.&lt;/p&gt;

&lt;p&gt;The architectural benefit is that horizontal serving does not introduce shared mutable state coordination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor IX — Disposability: Predictable startup and graceful shutdown
&lt;/h3&gt;

&lt;p&gt;A service should start predictably and shut down cleanly.&lt;/p&gt;

&lt;p&gt;The portable Node server verifies its release files before accepting traffic.&lt;/p&gt;

&lt;p&gt;It handles &lt;code&gt;SIGTERM&lt;/code&gt; and &lt;code&gt;SIGINT&lt;/code&gt;, stops accepting new work, and allows active responses to drain within a configurable timeout.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SHUTDOWN_TIMEOUT_MS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the shutdown grace period expires, remaining connections are terminated.&lt;/p&gt;

&lt;p&gt;The application also implements browser-side recovery.&lt;/p&gt;

&lt;p&gt;React error boundaries provide a fallback interface if rendering fails. Users can reload the application or download a backup of saved assessments.&lt;/p&gt;

&lt;p&gt;This is particularly important when a deployment removes a JavaScript chunk that an older browser session is still attempting to load.&lt;/p&gt;

&lt;p&gt;Preserving previous immutable deployments and their hashed assets helps reduce such failures.&lt;/p&gt;

&lt;p&gt;The result is a layered recovery model covering both the serving process and the browser interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor X — Dev/prod parity: Test the production build
&lt;/h3&gt;

&lt;p&gt;A frequent weakness in prototype development is testing only the development server.&lt;/p&gt;

&lt;p&gt;Vite's development environment is not identical to the compiled, security-constrained production application.&lt;/p&gt;

&lt;p&gt;The RCA Calculator addresses this with browser tests that run against the actual production build served by the portable Node runtime.&lt;/p&gt;

&lt;p&gt;Playwright tests interact with the application as users would.&lt;/p&gt;

&lt;p&gt;They cover assessment workflows, persistence, imports, exports, mobile behavior, and accessibility checks.&lt;/p&gt;

&lt;p&gt;This matters because a development build may work while a production Content Security Policy blocks a library or a lazily loaded component.&lt;/p&gt;

&lt;p&gt;By validating the production artifact and its response headers, the tests exercise a more representative deployment.&lt;/p&gt;

&lt;p&gt;There is still a boundary: passing local production-server tests does not prove that Vercel's live CDN configuration, TLS, and project settings are correct.&lt;/p&gt;

&lt;p&gt;Those require post-deployment verification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor XI — Logs: Structured, privacy-conscious observability
&lt;/h3&gt;

&lt;p&gt;Operational diagnostics are essential when hardening an application.&lt;/p&gt;

&lt;p&gt;The portable Node server emits structured JSON events to standard output.&lt;/p&gt;

&lt;p&gt;Request events include information such as:&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;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http_request"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"generated-request-id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"asset"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"durationMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"artifactId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"release-artifact-id"&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;The server intentionally avoids logging scenario content, query strings, request bodies, and assessment details.&lt;/p&gt;

&lt;p&gt;Browser diagnostics also use predefined event codes.&lt;/p&gt;

&lt;p&gt;For example, a render failure can produce an event containing its type, application version, and revision without exposing the user's model inputs.&lt;/p&gt;

&lt;p&gt;These logging decisions are important because the application may hold commercially sensitive assessment assumptions.&lt;/p&gt;

&lt;p&gt;However, browser console messages are not automatically collected into a central monitoring platform.&lt;/p&gt;

&lt;p&gt;Operational logging therefore has two distinct boundaries:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Host-managed access and runtime logs.&lt;/li&gt;
&lt;li&gt;Local browser diagnostics that would need an explicitly designed collection mechanism for remote monitoring.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Retention, access controls, alerting, and centralized observability remain hosting responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factor XII — Admin processes: Controlled one-off operations
&lt;/h3&gt;

&lt;p&gt;Traditional applications may require administrative commands for migrations, data repair, and database maintenance.&lt;/p&gt;

&lt;p&gt;The RCA Calculator does not have server-side migrations or account administration.&lt;/p&gt;

&lt;p&gt;Its one-off operational commands include release verification, dependency audits, and scenario validation.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run validate:scenario &lt;span class="nt"&gt;--&lt;/span&gt; ./assessment.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This validates a local assessment using the application's model rules.&lt;/p&gt;

&lt;p&gt;The validator can identify invalid records without uploading the user's assessment or modifying the source file.&lt;/p&gt;

&lt;p&gt;The principle is straightforward: operational utilities should use the same validated codebase as the application and should behave predictably.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Security hardening beyond the Twelve-Factor methodology
&lt;/h2&gt;

&lt;p&gt;Although Twelve-Factor is a useful architecture framework, it is not a complete security standard.&lt;/p&gt;

&lt;p&gt;For a browser application, additional controls are necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content Security Policy
&lt;/h3&gt;

&lt;p&gt;The Vercel configuration defines a Content Security Policy that restricts script loading and network connections to the application's origin.&lt;/p&gt;

&lt;p&gt;Key directives include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;default-src 'self'
script-src 'self'
connect-src 'self'
object-src 'none'
frame-ancestors 'none'
form-action 'none'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This limits several classes of unwanted browser behavior.&lt;/p&gt;

&lt;p&gt;The configuration still permits inline styles because of the application's React and chart-rendering requirements, but it does not permit inline scripts or &lt;code&gt;eval&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP response security headers
&lt;/h3&gt;

&lt;p&gt;Additional headers include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: no-referrer
Permissions-Policy:
  camera=(), microphone=(),
  geolocation=(), payment=()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These controls reduce unnecessary browser capabilities and help mitigate framing and content interpretation risks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static-server restrictions
&lt;/h3&gt;

&lt;p&gt;The portable Node server implements defensive serving behavior.&lt;/p&gt;

&lt;p&gt;It rejects unsupported HTTP methods, invalid paths, hidden-file access, and attempts to escape the designated release directory.&lt;/p&gt;

&lt;p&gt;Symbolic links are also rejected during release verification.&lt;/p&gt;

&lt;p&gt;Only intended static resources are exposed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defensive browser persistence
&lt;/h3&gt;

&lt;p&gt;An additional hardening feature appears in the way saved scenarios are restored.&lt;/p&gt;

&lt;p&gt;If some browser records are malformed, the application attempts to retain valid records instead of discarding the entire dataset.&lt;/p&gt;

&lt;p&gt;Automatic saving is paused when invalid records are detected, preventing the application from silently overwriting the original storage contents.&lt;/p&gt;

&lt;p&gt;The user is offered an explicit recovery path.&lt;/p&gt;

&lt;p&gt;This illustrates a useful defensive design principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When recovering from invalid state, preserve the original evidence rather than automatically destroying it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Performance engineering through selective loading
&lt;/h2&gt;

&lt;p&gt;Demo readiness also depends on responsiveness.&lt;/p&gt;

&lt;p&gt;An application that works correctly but takes too long to initialize can create an unreliable demonstration experience.&lt;/p&gt;

&lt;p&gt;The RCA Calculator uses React lazy loading and Vite's code-splitting capabilities.&lt;/p&gt;

&lt;p&gt;The results screen, scenario comparison interface, and export screen are loaded on demand.&lt;/p&gt;

&lt;p&gt;Excel generation is also deferred until the user requests it.&lt;/p&gt;

&lt;p&gt;For example, the application uses a dynamic import for the workbook generation module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;exportScenarioToExcel&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../export/excel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;exportScenarioToExcel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scenario&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents the Excel generation library from unnecessarily increasing the initial application payload.&lt;/p&gt;

&lt;p&gt;The repository also defines an initial JavaScript bundle budget of &lt;strong&gt;450,000 bytes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The budget is checked automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run check:bundle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The check traverses the initial JavaScript dependency graph using the Vite build manifest and fails if the budget is exceeded.&lt;/p&gt;

&lt;p&gt;This is an effective example of turning a non-functional architecture requirement into an automated build gate.&lt;/p&gt;

&lt;p&gt;The ExcelJS deferred bundle remains relatively large, approximately 947 kB before compression according to the repository documentation, but it is not part of the initial load.&lt;/p&gt;

&lt;p&gt;That trade-off is visible rather than hidden.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Establishing confidence through automated testing
&lt;/h2&gt;

&lt;p&gt;Perhaps the most important transition from prototype to demo-ready software is moving from informal testing to repeatable evidence.&lt;/p&gt;

&lt;p&gt;The RCA Calculator has several testing layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unit and domain tests
&lt;/h3&gt;

&lt;p&gt;Vitest is used to test calculation behavior, including reference arithmetic, model validation, uncertainty aggregation, sensitivity analysis, and export correctness.&lt;/p&gt;

&lt;p&gt;These tests help ensure that changes to components or model assumptions do not unexpectedly change calculations.&lt;/p&gt;

&lt;h3&gt;
  
  
  End-to-end browser testing
&lt;/h3&gt;

&lt;p&gt;Playwright validates real browser workflows.&lt;/p&gt;

&lt;p&gt;This includes scenario management, report generation, browser persistence, imports, exports, and responsive behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility checks
&lt;/h3&gt;

&lt;p&gt;The testing stack integrates axe-core with Playwright to identify serious accessibility violations.&lt;/p&gt;

&lt;p&gt;Automated accessibility validation is valuable, but it does not replace human keyboard-navigation and screen-reader testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operational verification
&lt;/h3&gt;

&lt;p&gt;The repository contains Node operational tests for serving behavior, security headers, runtime lifecycle, and release integrity.&lt;/p&gt;

&lt;p&gt;This is especially useful for verifying the architectural requirements that do not fit naturally into React unit tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Continuous integration
&lt;/h3&gt;

&lt;p&gt;GitHub Actions runs the validation process on pushes and pull requests.&lt;/p&gt;

&lt;p&gt;The pipeline follows this pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Checkout Repository
        |
        v
Setup Node.js 24
        |
        v
npm ci --include=dev
        |
        v
Dependency Audit
        |
        v
Unit Tests
        |
        v
Production Build
        |
        v
Bundle Budget Check
        |
        v
Release Integrity Check
        |
        v
Operational Tests
        |
        v
Playwright Browser Tests
        |
        v
Retain Tested Artifact
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting static artifact is retained by CI, while failed browser tests can provide diagnostic traces.&lt;/p&gt;

&lt;p&gt;Importantly, the workflow validates and retains the release artifact; it does not automatically publish the application.&lt;/p&gt;

&lt;p&gt;Separating validation from promotion provides an additional opportunity for controlled deployment approval.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Architecture hardening as measurable engineering controls
&lt;/h2&gt;

&lt;p&gt;A useful lesson from this exercise is that architecture reviews become more valuable when principles translate into verifiable controls.&lt;/p&gt;

&lt;p&gt;Rather than treating architecture as a collection of diagrams and recommendations, each significant quality requirement can be associated with implementation evidence.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Architecture quality&lt;/th&gt;
&lt;th&gt;Hardening mechanism&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reproducibility&lt;/td&gt;
&lt;td&gt;Locked dependencies and pinned runtime&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;package-lock.json&lt;/code&gt;, &lt;code&gt;.nvmrc&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintainability&lt;/td&gt;
&lt;td&gt;Separation of UI, domain, and export logic&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;src/&lt;/code&gt; modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Correctness&lt;/td&gt;
&lt;td&gt;Domain validation and unit tests&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;model.ts&lt;/code&gt;, &lt;code&gt;tests/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;CSP, input validation, server restrictions&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;vercel.json&lt;/code&gt;, serving code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Lazy loading and size budgets&lt;/td&gt;
&lt;td&gt;Vite build and bundle checker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reliability&lt;/td&gt;
&lt;td&gt;Error boundaries and recovery&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ErrorBoundary.tsx&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployability&lt;/td&gt;
&lt;td&gt;Immutable artifacts and integrity checks&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;release.json&lt;/code&gt; and verification scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operability&lt;/td&gt;
&lt;td&gt;Health checks and structured logs&lt;/td&gt;
&lt;td&gt;Portable Node server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testability&lt;/td&gt;
&lt;td&gt;Unit, operational, browser, and accessibility tests&lt;/td&gt;
&lt;td&gt;Vitest, Playwright, GitHub Actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data protection&lt;/td&gt;
&lt;td&gt;Local persistence and explicit backup paths&lt;/td&gt;
&lt;td&gt;Scenario management and JSON export&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is the point where architectural maturity becomes observable.&lt;/p&gt;

&lt;p&gt;The application is not considered hardened merely because someone has documented good intentions.&lt;/p&gt;

&lt;p&gt;It is hardened to the extent that those intentions are represented by controls, tests, and operational procedures.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. What the hardening achieved
&lt;/h2&gt;

&lt;p&gt;The architectural work produced several meaningful improvements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, a more deterministic build and release process.&lt;/strong&gt; By using a locked toolchain and immutable release files, the deployed artifact can be identified and checked independently of a developer's local environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, better separation of concerns.&lt;/strong&gt; The domain engine, model data, user interface, exports, and deployment tooling have clearer boundaries, making it easier to inspect and change the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third, stronger failure handling.&lt;/strong&gt; Malformed scenario records, unavailable local storage, render failures, and shutdown events are handled more deliberately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fourth, an improved browser security posture.&lt;/strong&gt; Explicit response headers, restricted formula execution, input validation, and defensive static serving reduce avoidable exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fifth, automated quality gates.&lt;/strong&gt; Tests, dependency audits, release verification, and bundle checks help catch issues before a demonstration or deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finally, reduced operational complexity.&lt;/strong&gt; By preserving a static-client architecture, the application avoids unnecessary infrastructure while retaining clear pathways for future evolution.&lt;/p&gt;

&lt;p&gt;These are architectural and operational improvements, rather than measured claims about runtime speed, service uptime, or production traffic capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. What remains outside demo hardening
&lt;/h2&gt;

&lt;p&gt;Demo hardening is not equivalent to claiming unrestricted production readiness.&lt;/p&gt;

&lt;p&gt;The repository documents several important limits.&lt;/p&gt;

&lt;p&gt;The application is not a certified environmental assessment engine. Domain review and independent model assurance would be needed before using its outputs as formally assured scientific claims.&lt;/p&gt;

&lt;p&gt;Browser-local persistence does not provide enterprise-grade durability, centralized backup, or account synchronization.&lt;/p&gt;

&lt;p&gt;Live Vercel deployment configuration must be verified after release. Repository declarations do not prove that hosting-level controls, monitoring, DNS, TLS, and deployment permissions are correctly configured.&lt;/p&gt;

&lt;p&gt;The documented moderate transitive dependency advisory still requires continued monitoring.&lt;/p&gt;

&lt;p&gt;And while CI provides substantial automated coverage, performance capacity testing, human accessibility review, and organizational risk acceptance are separate activities.&lt;/p&gt;

&lt;p&gt;This distinction is central to responsible engineering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A successful hardening effort should make the system's capabilities clearer without hiding its limitations.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Lessons learned: From rapid prototyping to architecture discipline
&lt;/h2&gt;

&lt;p&gt;This project reinforced several engineering lessons.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture principles are more important than architectural fashion
&lt;/h3&gt;

&lt;p&gt;A system does not need microservices, containers, distributed caches, and multiple databases to qualify as well architected.&lt;/p&gt;

&lt;p&gt;Architecture quality is better judged by how effectively a design meets its actual requirements and controls its risks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Twelve-Factor is a methodology, not a technology checklist
&lt;/h3&gt;

&lt;p&gt;The twelve factors helped structure the review around reproducibility, configuration, deployment, statelessness, operational behavior, and test parity.&lt;/p&gt;

&lt;p&gt;Applying them intelligently was more useful than forcing the application into an inappropriate backend architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automated tests should protect both functionality and architecture
&lt;/h3&gt;

&lt;p&gt;Calculation tests protect the scientific model.&lt;/p&gt;

&lt;p&gt;Browser tests protect user journeys.&lt;/p&gt;

&lt;p&gt;Operational tests protect runtime behavior.&lt;/p&gt;

&lt;p&gt;Security and bundle checks protect non-functional quality requirements.&lt;/p&gt;

&lt;p&gt;Together, these give stronger evidence than relying on manual UI testing alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Immutability improves confidence in demonstrations
&lt;/h3&gt;

&lt;p&gt;Being able to identify and verify the exact artifact being served reduces uncertainty during deployment and rollback.&lt;/p&gt;

&lt;p&gt;A demo should not depend on a server silently rebuilding code or resolving different dependencies at startup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defensive design matters as much as the happy path
&lt;/h3&gt;

&lt;p&gt;Applications are often judged by what happens when something goes wrong.&lt;/p&gt;

&lt;p&gt;Graceful error screens, preserved browser data, explicit export errors, bounded inputs, and predictable shutdown behavior all contribute to trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI can accelerate implementation, but engineering accountability remains essential
&lt;/h3&gt;

&lt;p&gt;AI-assisted development makes generating software easier.&lt;/p&gt;

&lt;p&gt;It does not remove the need to establish architectural boundaries, validate assumptions, test calculations, manage dependencies, and understand operational risks.&lt;/p&gt;

&lt;p&gt;The transition from vibe-coded prototype to demo-ready application is therefore not simply a refactoring exercise.&lt;/p&gt;

&lt;p&gt;It is the process of turning experimental code into a system with explicit, testable engineering properties.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Conclusion
&lt;/h2&gt;

&lt;p&gt;The RCA Calculator demonstrates that a relatively lightweight browser application can benefit significantly from formal architecture hardening.&lt;/p&gt;

&lt;p&gt;By applying the Twelve-Factor App methodology pragmatically, separating domain logic from presentation, enforcing dependency reproducibility, implementing immutable releases, strengthening browser security, and introducing automated validation, the application has a more disciplined foundation for demonstrations and further development.&lt;/p&gt;

&lt;p&gt;The most important architectural decision was not adding infrastructure.&lt;/p&gt;

&lt;p&gt;It was &lt;strong&gt;making the existing architecture reliable, understandable, testable, and operationally explicit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is a useful approach for anyone developing AI-assisted proof-of-concepts, research tools, internal applications, or early-stage products.&lt;/p&gt;

&lt;p&gt;Vibe coding can help us reach a working prototype quickly.&lt;/p&gt;

&lt;p&gt;Software engineering discipline is what helps us demonstrate it with confidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Source code and technical references
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Project repository:&lt;/strong&gt; &lt;a href="https://github.com/scha54/RCA-Calculator" rel="noopener noreferrer"&gt;https://github.com/scha54/RCA-Calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live application:&lt;/strong&gt; &lt;a href="https://rca-calculator.vercel.app" rel="noopener noreferrer"&gt;https://rca-calculator.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Twelve-Factor architecture assessment:&lt;/strong&gt; &lt;a href="https://github.com/scha54/RCA-Calculator/blob/master/docs/TWELVE_FACTOR.md" rel="noopener noreferrer"&gt;https://github.com/scha54/RCA-Calculator/blob/master/docs/TWELVE_FACTOR.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operations runbook:&lt;/strong&gt; &lt;a href="https://github.com/scha54/RCA-Calculator/blob/master/docs/OPERATIONS.md" rel="noopener noreferrer"&gt;https://github.com/scha54/RCA-Calculator/blob/master/docs/OPERATIONS.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calculation methodology:&lt;/strong&gt; &lt;a href="https://github.com/scha54/RCA-Calculator/blob/master/docs/METHODOLOGY.md" rel="noopener noreferrer"&gt;https://github.com/scha54/RCA-Calculator/blob/master/docs/METHODOLOGY.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Release verification documentation:&lt;/strong&gt; &lt;a href="https://github.com/scha54/RCA-Calculator/blob/master/docs/RELEASE.md" rel="noopener noreferrer"&gt;https://github.com/scha54/RCA-Calculator/blob/master/docs/RELEASE.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Twelve-Factor App methodology:&lt;/strong&gt; &lt;a href="https://12factor.net/" rel="noopener noreferrer"&gt;https://12factor.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article describes the repository architecture and documented hardening controls as reviewed on October 24, 2026. The project remains a screening and demonstration application; deployment assurance and scientific certification are separate considerations.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What practices do you use to move AI-generated prototypes toward demo-ready or production-ready software? I'd be interested to hear how others are applying architecture principles without introducing unnecessary complexity.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>react</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Memory Lane AI — Privacy-First Family Memory Storyteller 📖✨</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Thu, 15 Oct 2026 19:19:49 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/memory-lane-ai-privacy-first-family-memory-storyteller-4f7g</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/memory-lane-ai-privacy-first-family-memory-storyteller-4f7g</guid>
      <description>&lt;p&gt;Every family possesses an irreplaceable archive of oral lore: the story of how grandparents migrated during tough times, the secret spices behind a holiday stew, or childhood summers spent climbing mango trees. Yet, most of these memories remain trapped in fragile photo boxes, disjointed voice memos on old phones, or fading recollections.&lt;/p&gt;

&lt;p&gt;Commercial "AI biography" apps have attempted to address this, but they introduce a severe compromise: they require you to upload your family’s most intimate photographs, private recordings, and personal names to closed, cloud-hosted LLM services. For families protective of their privacy—or those preserving memories for elderly relatives—giving proprietary third-party servers perpetual access to family data is an absolute dealbreaker.&lt;/p&gt;

&lt;p&gt;Memory Lane AI solves this problem by combining 100% local-first data sovereignty with open-source, on-device AI.&lt;/p&gt;

&lt;p&gt;What I Built&lt;br&gt;
Memory Lane AI is a local-first web application that helps families capture, organize, transcribe, and craft oral histories and heirloom photographs into timeless storybooks and archival, downloadable PDFs—with zero personal data leaving the user’s computer.&lt;/p&gt;

&lt;p&gt;┌────────────────────────────────────────────────────────────────────────┐&lt;br&gt;
│                        Memory Lane AI Architecture                     │&lt;br&gt;
├────────────────────────────────────────────────────────────────────────┤&lt;br&gt;
│  [ React 19 + TypeScript + Vite 8 Frontend ]                          │&lt;br&gt;
│   ├─ 15 Archival Screens (Vault, Timelines, Audio Recorder, Wizard)    │&lt;br&gt;
│   ├─ IndexedDB (Dexie.js) ──► 100% On-Device Photos, Audio &amp;amp; Records   │&lt;br&gt;
│   └─ jsPDF &amp;amp; html2canvas ──► High-Resolution Archival Storybook PDFs   │&lt;br&gt;
│                                │                                       │&lt;br&gt;
│                       (Local HTTP / CORS)                              │&lt;br&gt;
│                                ▼                                       │&lt;br&gt;
│  [ Python 3.14 FastAPI Microservice (localhost:8000) ]                 │&lt;br&gt;
│   ├─ Modular Whisper Adapter ──► faster-whisper / openai-whisper (CPU) │&lt;br&gt;
│   └─ Modular Ollama Adapter  ──► Local LLMs (Llama 3, Mistral, Qwen)   │&lt;br&gt;
│                                │                                       │&lt;br&gt;
│        (Automatic Fallback) ───┴───► [ Client-Side Grounded Engine ]   │&lt;br&gt;
└────────────────────────────────────────────────────────────────────────┘&lt;br&gt;
The 15-Screen Archival Suite&lt;br&gt;
Welcome &amp;amp; Onboarding: Privacy manifest, local storage breakdown, and one-click demo archive loader.&lt;br&gt;
Dashboard: Archival metrics, memory carousel, family members shelf, and active storybooks.&lt;br&gt;
Memories Library: Filter by media type (photo, audio, text, mixed), people, tags, and date range.&lt;br&gt;
Memory Details: Lightbox viewer, audio player with animated waveform, dual transcript viewer, and cited stories.&lt;br&gt;
Add / Edit Memory: Multi-photo upload with instant previews, audio attachments, and date precision selectors (Exact, Month, Year, Approximate, Unknown).&lt;br&gt;
People Directory: Family roster with relationship tags, birth/death years, and memory counters.&lt;br&gt;
Person Profile &amp;amp; Timeline: Chronological, interactive life timeline for any family member.&lt;br&gt;
Places &amp;amp; Events: Geographical clustering and milestones across family journeys.&lt;br&gt;
Audio Recording &amp;amp; Transcription: In-browser microphone recorder with live VU level meter, timer, and transcription runner.&lt;br&gt;
AI Story Creator Wizard: Multi-step wizard selecting source memories, tone (Warm &amp;amp; nostalgic, Simple &amp;amp; conversational, Documentary &amp;amp; factual, Child-friendly, Memoir style), and prompt constraints.&lt;br&gt;
Story Editor: Section-by-section narrative editor with source memory citations and uncertainty tags.&lt;br&gt;
Storybooks &amp;amp; Chapters: Book manager, chapter reordering, cover photo selection, and thematic styling.&lt;br&gt;
Storybook Preview &amp;amp; Export: Paginated book preview with high-resolution PDF exporter.&lt;br&gt;
Global Search: Instant multi-field search across titles, captions, transcripts, and tags.&lt;br&gt;
Settings &amp;amp; Sovereignty: Live navigator.storage quota meter, AI backend connectivity status, full JSON backup export, and safe restore.&lt;br&gt;
Who Would Pay For It? (The Side Hustle Opportunity)&lt;br&gt;
Memory Lane AI was built with a viable, multi-tiered monetization strategy tailored for personal historians and privacy-conscious families:&lt;/p&gt;

&lt;p&gt;Boutique Family Biography &amp;amp; Oral History Agency:&lt;br&gt;
Target: High-net-worth families, adult children recording aging parents, and estate planners.&lt;br&gt;
Offering: Professional memory capture sessions. Armed with Memory Lane AI running entirely on a local laptop, an oral historian visits elderly family members, records high-fidelity audio, imports family albums, generates grounded chapters with local open-weight models, and delivers heirloom hardcover books printed from the exported PDFs.&lt;br&gt;
Price Point: $500 – $2,500 per completed family storybook.&lt;br&gt;
Turnkey Archival Software for Senior Living &amp;amp; Memory Care Facilities:&lt;br&gt;
Target: Assisted living centers, memory care communities, and hospice providers.&lt;br&gt;
Offering: An on-premise, HIPAA-compliant memory vault. Because zero personal data, medical details, or elder voices leave the building, care facilities can safely capture residents' life stories for therapeutic reminiscence therapy and family keepsakes.&lt;br&gt;
Price Point: $99 – $199/month per facility license.&lt;br&gt;
Print-on-Demand Keepsake Integration:&lt;br&gt;
Offering: Direct export pipeline from the application's structured PDF engine to custom photo-book printers (e.g., Blurb, Gelato) with built-in affiliate or print markups.&lt;br&gt;
Code&lt;br&gt;
The complete source code for Memory Lane AI is available under an open-source license:&lt;/p&gt;

&lt;p&gt;👉 GitHub Repository: &lt;a href="https://github.com/scha54/Hactoberfest-Hackathon-Week-2" rel="noopener noreferrer"&gt;https://github.com/scha54/Hactoberfest-Hackathon-Week-2&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Grounded AI Story Generation via Local Ollama
To eliminate hallucinations (such as inventing relatives, dates, or events not present in the family's oral notes), the backend sends a strict JSON schema prompt to the local Ollama instance:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;python&lt;/p&gt;

&lt;h1&gt;
  
  
  backend/app/adapters/ollama_story.py
&lt;/h1&gt;

&lt;p&gt;class OllamaStoryAdapter(AIStoryAdapter):&lt;br&gt;
    """&lt;br&gt;
    Integrates with local Ollama LLMs (Llama 3, Mistral, Qwen, etc.).&lt;br&gt;
    Uses a strictly grounded prompt to prevent hallucinations and formats output as JSON.&lt;br&gt;
    Gracefully falls back to MockStoryAdapter if Ollama is unreachable.&lt;br&gt;
    """&lt;br&gt;
    async def generate_story(self, request: StoryGenerationRequest) -&amp;gt; StoryGenerationResponse:&lt;br&gt;
        system_prompt = (&lt;br&gt;
            "You are a family memory archivist and biographer. Your task is to write a warm, beautifully structured "&lt;br&gt;
            "family storybook chapter strictly grounded in the memories, transcripts, captions, and names provided.\n\n"&lt;br&gt;
            "CRITICAL CONSTRAINTS:\n"&lt;br&gt;
            "1. ONLY use details, places, names, and events explicitly provided in the user prompt.\n"&lt;br&gt;
            "2. DO NOT hallucinate dates, relatives, fictional drama, or unseen events.\n"&lt;br&gt;
            "3. If any detail is uncertain, approximate, or missing, add a note in the 'uncertainties' list.\n"&lt;br&gt;
            "4. Respond strictly with a valid JSON object matching the schema."&lt;br&gt;
        )&lt;br&gt;
        payload = {&lt;br&gt;
            "model": self.model,&lt;br&gt;
            "messages": [&lt;br&gt;
                {"role": "system", "content": system_prompt},&lt;br&gt;
                {"role": "user", "content": json.dumps(user_content, ensure_ascii=False)}&lt;br&gt;
            ],&lt;br&gt;
            "stream": False,&lt;br&gt;
            "format": "json"&lt;br&gt;
        }&lt;br&gt;
        async with httpx.AsyncClient(timeout=45.0) as client:&lt;br&gt;
            res = await client.post(f"{self.base_url}/api/chat", json=payload)&lt;br&gt;
            # Parses sections, source citations, and uncertainty flags...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Local-First Client Persistence (Dexie.js &amp;amp; IndexedDB)
All audio recordings, binary photo blobs, people profiles, and books are stored entirely within the client's browser IndexedDB:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;typescript&lt;br&gt;
// frontend/src/db/index.ts&lt;br&gt;
import Dexie, { type Table } from 'dexie';&lt;br&gt;
import type { Memory, Person, Story, Storybook, AppSettings } from '../types';&lt;br&gt;
export class MemoryLaneDB extends Dexie {&lt;br&gt;
  memories!: Table;&lt;br&gt;
  people!: Table;&lt;br&gt;
  stories!: Table;&lt;br&gt;
  storybooks!: Table;&lt;br&gt;
  settings!: Table;&lt;br&gt;
  constructor() {&lt;br&gt;
    super('MemoryLaneAI_DB');&lt;br&gt;
    this.version(1).stores({&lt;br&gt;
      memories: 'id, title, datePrecision, place, createdAt, updatedAt, *tags, *peopleIds',&lt;br&gt;
      people: 'id, fullName, relationship, birthYear, deathYear, createdAt, *tags',&lt;br&gt;
      stories: 'id, title, tone, status, createdAt, updatedAt, *sourceMemoryIds',&lt;br&gt;
      storybooks: 'id, title, createdAt, updatedAt',&lt;br&gt;
      settings: 'id'&lt;br&gt;
    });&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
How I Built It&lt;br&gt;
Memory Lane AI was engineered from the ground up using open-source AI models, open-source frameworks, and local-first browser storage:&lt;/p&gt;

&lt;p&gt;Component   Technology  Role&lt;br&gt;
Local LLM Engine    Ollama (&lt;a href="http://localhost:11434" rel="noopener noreferrer"&gt;http://localhost:11434&lt;/a&gt;) Open-weight models (Llama 3, Mistral, Qwen 2.5, Phi-3) executing on-device inference via structured JSON mode.&lt;br&gt;
Speech Recognition  faster-whisper / Whisper    Quantized (int8) automatic speech recognition running locally on CPU/GPU for transcribed oral recordings.&lt;br&gt;
Backend API FastAPI + Pydantic + Uvicorn    Python 3.14 asynchronous microservice exposing lightweight endpoints (/api/health, /api/capabilities, /api/stories/generate, /api/transcribe).&lt;br&gt;
Frontend Framework  React 19 + TypeScript (Strict)  Component tree with 15 dedicated views, client-side routing, and responsive tactile layout.&lt;br&gt;
Styling &amp;amp; Design Tokens Vanilla CSS + Archival Tokens   Warm ivory backgrounds (#FAF7F2), charcoal espresso typography (#2C2523), terracotta accents (#C86D51), and serif headings.&lt;br&gt;
Persistence Engine  Dexie.js (IndexedDB)    Multi-gigabyte browser-local storage holding binary blobs, audio tracks, and relational metadata.&lt;br&gt;
PDF Generation  jsPDF + html2canvas Automated typesetting engine producing multi-page, print-ready PDF storybooks with custom borders, dedications, and source citations.&lt;br&gt;
Two-Tier Graceful Degradation Architecture&lt;br&gt;
A core engineering requirement was that the app must never fail or lock the user out if the AI backend is unreachable.&lt;/p&gt;

&lt;p&gt;Tier 1 (Full Local AI): If Ollama and FastAPI are running on localhost:8000, full speech-to-text with Whisper and grounded LLM generation are enabled.&lt;br&gt;
Tier 2 (Client-Side Fallback): If running completely offline or without Python, the frontend automatically switches to a deterministic client-side story compiler (generateClientGroundedStory) and an oral history transcription simulator. Users can still record voice memos, create memories, manage people, assemble chapters, and export PDFs without any backend running.&lt;br&gt;
Why Does Open Innovation Matter?&lt;br&gt;
Open innovation is essential for projects involving personal human stories and family heritage:&lt;/p&gt;

&lt;p&gt;Family Intimacy and Data Sovereignty: Closed AI services (OpenAI, Anthropic, Google Cloud) operate on multi-tenant infrastructure where inputs may be logged, reviewed by human moderators, or used for model training. Handing over high-resolution pictures of one's children, voice recordings of an ailing grandparent, or personal family triumphs to a closed commercial cloud compromises privacy. Open-weight models running on Ollama restore complete sovereign ownership: no packets cross the wire.&lt;br&gt;
Permanence and Digital Longevity: Family archives must survive for decades. Closed APIs frequently deprecate endpoints, change pricing tiers, alter moderation policies, or terminate operations entirely. Open-source models and open standards (such as IndexedDB and client-generated PDFs) guarantee that an archive created today remains accessible decades from now, independent of any corporate roadmap.&lt;br&gt;
Predictable Unit Economics: For a family historian or side-hustle biographic agency, per-token API fees can fluctuate wildly when transcribing hours of raw audio and synthesizing multi-chapter books. With open-weight models (Llama 3, Whisper), inference costs are flat: zero API bills, regardless of how many stories are preserved.&lt;br&gt;
Retrospective: What Went Well, What Did Not, and Lessons Learned&lt;br&gt;
What Went Well&lt;br&gt;
Strictly Grounded Prompting: Constraining Ollama to a validated JSON schema with explicit sourceMemoryIds and an uncertainties array completely eliminated fabricated dates and fictitious relatives.&lt;br&gt;
Robust Local Storage via Dexie.js: Storing large binary photo Blobs and WebM audio files directly in IndexedDB provided snappy, offline-first performance without needing any external database servers.&lt;br&gt;
Automated Verification: The Python backend achieved 100% test coverage across all endpoints (pytest passing 4/4), and the React frontend passed strict oxlint checks with 0 warnings and 0 errors, accompanied by a clean TypeScript build.&lt;br&gt;
What Did Not Go Well&lt;br&gt;
Audio Codec Cross-Browser Fragmentation: The native browser MediaRecorder API defaults to audio/webm;codecs=opus on Chromium browsers, but Whisper expects raw audio or WAV streams. We had to ensure temporary file conversion and fallback handling in the Python adapter.&lt;br&gt;
Large Production Bundle Size: Vite's production build reported a warning on the main chunk (dist/assets/index-BggqEAK5.js at ~1.29 MB). This was caused by statically bundling heavy client-side libraries (jspdf and html2canvas) into the main entry point rather than lazily loading them via dynamic import().&lt;br&gt;
Open-Weight Model Variance: While Llama 3 and Qwen 2.5 adhered closely to the JSON formatting instructions, smaller parameter models (e.g., 1B–3B models) occasionally enclosed their outputs in markdown fences (json ... ) or omitted required uncertainty arrays. We implemented custom JSON extraction logic to handle these edge cases cleanly.&lt;br&gt;
Lessons Learned&lt;br&gt;
AI as an Enhancement, Not a Prerequisite: Structuring the software so that every core feature (data entry, timeline organization, chapter editing, PDF compilation) works 100% offline without AI creates a rock-solid, resilient application.&lt;br&gt;
Transparent Storage Drives User Confidence: Providing a real-time storage quota meter and full one-click JSON backup/restore in the UI fundamentally transformed user trust. When users can see that their photos and audio are stored strictly on their physical machine, their willingness to record genuine, intimate memories increases dramatically.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Preserving Grandma's Recipes &amp; Stories: Building a 100% Private, Source-Grounded Family Cookbook with Open-Source AI</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Sun, 04 Oct 2026 18:37:50 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/preserving-grandmas-recipes-stories-building-a-100-private-source-grounded-family-cookbook-340b</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/preserving-grandmas-recipes-stories-building-a-100-private-source-grounded-family-cookbook-340b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




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

&lt;p&gt;Every family has a treasure trove of secret recipes, culinary tips, and cherished memories. But for most of us, these aren't written down in neat cookbooks or standardized digital apps—they are hidden inside informal WhatsApp voice messages, spoken anecdotes over dinner, and cassette tapes passed down across generations.&lt;/p&gt;

&lt;p&gt;When my grandmother cooks, she doesn't measure in grams or follow 10-minute timers. She cooks by feel and memory:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Take a handful of fresh cumin seeds, roast them until fragrant like my mother used to do on Sunday afternoons in Jaipur, then add potatoes until soft..."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Traditional recipe apps fail here because they demand rigid structured inputs. On the flip side, commercial cloud AI services present two severe flaws:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Privacy &amp;amp; Sensitivity&lt;/strong&gt;: Sending intimate family voice recordings, personal names, and vocal biometrics to third-party cloud LLM APIs surrenders private heritage to remote servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Hallucinations &amp;amp; Distortion&lt;/strong&gt;: Standard AI generators tend to "fix" recipes by inventing missing quantities (e.g. inserting &lt;em&gt;1 tsp salt&lt;/em&gt; or &lt;em&gt;10 mins prep time&lt;/em&gt;) when Grandma never specified them, mangling family tradition into generic generic web recipes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To solve this, I built &lt;strong&gt;Grandma's Kitchen&lt;/strong&gt;—a 100% local, privacy-first, AI-powered family cookbook and memory archive. &lt;/p&gt;

&lt;h3&gt;
  
  
  What Grandma's Kitchen Does:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Voice-to-Recipe Extraction&lt;/strong&gt;: Ingests raw audio recordings or live browser voice notes and transcribes them locally via Whisper STT.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict Source Grounding &amp;amp; Anti-Hallucination&lt;/strong&gt;: Extracts ingredients, steps, and timings into structured recipe cards without ever inventing missing details. Unspecified quantities are marked as &lt;code&gt;null&lt;/code&gt; with &lt;code&gt;confidence: "unknown"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory vs. Cooking Separation&lt;/strong&gt;: Separates personal anecdotes (&lt;em&gt;"My mother made this every Diwali..."&lt;/em&gt;) from step-by-step cooking instructions, preserving family memories in a dedicated memory archive tab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Provenance Inspector&lt;/strong&gt;: Every extracted ingredient, step, and story maintains line-by-line provenance linking directly back to original audio transcript quotes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Semantic Search&lt;/strong&gt;: Allows family members to search by natural questions (&lt;em&gt;"What did Grandma make on cold rainy days?"&lt;/em&gt;) using local vector embeddings.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Watch the complete project overview and live walkthrough below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/_DpzWddPI2k" rel="noopener noreferrer"&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%2F7qjdp34ywu8t10clwwxc.jpg" alt="Grandma's Kitchen Video Demo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📺 &lt;strong&gt;Video Link&lt;/strong&gt;: &lt;a href="https://youtu.be/_DpzWddPI2k" rel="noopener noreferrer"&gt;Watch Grandma's Kitchen Demo on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features Highlighted in the Demo:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🎙️ &lt;strong&gt;Live Audio Ingestion&lt;/strong&gt;: Browser recording with waveform display and instant file upload support for &lt;code&gt;.wav&lt;/code&gt;, &lt;code&gt;.mp3&lt;/code&gt;, &lt;code&gt;.m4a&lt;/code&gt;, and &lt;code&gt;.ogg&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Source Provenance Modal&lt;/strong&gt;: Clicking on any ingredient or cooking step opens an evidence drawer showing the exact transcript excerpt and audio context supporting that fact.&lt;/li&gt;
&lt;li&gt;📖 &lt;strong&gt;Family Memory Archive&lt;/strong&gt;: View captured stories, relatives mentioned, and cultural occasions tied to each dish.&lt;/li&gt;
&lt;li&gt;🖨️ &lt;strong&gt;Printable Family Cookbook&lt;/strong&gt;: Clean, print-ready CSS stylesheet for exporting physical family heirloom cookbooks.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;The entire codebase is open-source and available on GitHub:&lt;/p&gt;

&lt;p&gt;🐙 &lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/scha54/Hactoberfest-Weekend-Challenge" rel="noopener noreferrer"&gt;scha54/Hactoberfest-Weekend-Challenge&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grandmas-kitchen/
├── backend/
│   ├── app/
│   │   ├── api/             # FastAPI REST endpoints (recordings, recipes, search)
│   │   ├── core/            # Config, database initialization, security
│   │   ├── db/              # SQLite database session &amp;amp; models
│   │   ├── schemas/         # Pydantic data schemas &amp;amp; JSON specs
│   │   └── services/
│   │       ├── extraction/  # Ollama LLM provider &amp;amp; strict source-grounding prompts
│   │       ├── transcription/# OpenAI Whisper local audio transcription engine
│   │       ├── embeddings/  # Local vector embedding generation
│   │       └── search/      # Local cosine similarity vector search
│   └── tests/               # Pytest suite for API endpoints &amp;amp; extraction logic
├── frontend/
│   ├── src/
│   │   ├── components/      # RecipeSteps, SourceEvidenceModal, AudioRecorder, etc.
│   │   ├── pages/           # UploadPage, CookbookPage, SearchPage, RecipeDetailPage
│   │   └── services/        # API client &amp;amp; audio streaming utilities
│   └── public/              # Static assets &amp;amp; sample recordings
├── data/                    # 100% local persistent storage (audio, SQLite DB, vectors)
└── scripts/                 # Cross-platform 1-click startup scripts (.ps1 &amp;amp; .sh)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;Grandma's Kitchen was designed from the ground up around &lt;strong&gt;local, open-source AI models&lt;/strong&gt; and a resilient provider abstraction architecture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                       Browser Web UI                        │
│             React + TypeScript + Vite + Tailwind            │
└──────────────────────────────┬──────────────────────────────┘
                               │ HTTP / JSON / Audio Stream
                               ▼
┌─────────────────────────────────────────────────────────────┐
│                    FastAPI Local Backend                    │
└──────┬───────────────────────┼──────────────────────┬───────┘
       │                       │                      │
       ▼                       ▼                      ▼
┌──────────────┐       ┌──────────────┐       ┌──────────────┐
│ Local STT    │       │ Local LLM    │       │ Embeddings   │
│ Whisper      │       │ Ollama       │       │ Local Vector │
└──────┬───────┘       └──────┬───────┘       └──────┬───────┘
       │                       │                      │
       └───────────────────────┼──────────────────────┘
                               ▼
┌─────────────────────────────────────────────────────────────┐
│                        Storage Layer                        │
│         SQLite (Metadata/Data) + Local Disk (Audio)         │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Local Speech-to-Text (Open-Weight Whisper)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: OpenAI Whisper open-weight models running locally via Python (&lt;code&gt;whisper&lt;/code&gt; / &lt;code&gt;torch&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function&lt;/strong&gt;: Audio files uploaded from the React frontend are written to &lt;code&gt;data/audio/&lt;/code&gt; and transcribed locally without leaving the computer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback&lt;/strong&gt;: Includes a native local Python fallback parser to ensure 100% testability even on resource-constrained systems without GPU acceleration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Local LLM Extraction &amp;amp; Anti-Hallucination Framework
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: &lt;strong&gt;Ollama&lt;/strong&gt; running open-weight LLMs (&lt;strong&gt;Llama 3&lt;/strong&gt;, &lt;strong&gt;Mistral&lt;/strong&gt;, or &lt;strong&gt;Qwen&lt;/strong&gt;) via local HTTP endpoints (&lt;code&gt;http://localhost:11434&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt Engineering &amp;amp; System Constraints&lt;/strong&gt;:
We engineered a strict 7-point System Prompt enforcing strict source grounding:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never invent missing quantities&lt;/strong&gt;: Unmentioned measurements become &lt;code&gt;quantity: null&lt;/code&gt; and &lt;code&gt;confidence: "unknown"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never assume culinary constants&lt;/strong&gt;: Vague instructions ("until brown") are kept verbatim rather than converted to guessed minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Categorize storytelling&lt;/strong&gt;: Anecdotes and mentions of relatives are placed into &lt;code&gt;stories[]&lt;/code&gt;, keeping cooking steps clean.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Require provenance&lt;/strong&gt;: For every extracted ingredient, step, and story, the LLM must output &lt;code&gt;source_text&lt;/code&gt; containing the exact transcript quote.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Local Vector Search &amp;amp; Embeddings
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: Local vector embedding engine calculating semantic dense vector representations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search Mechanics&lt;/strong&gt;: Cosine similarity search over recipe titles, ingredient vectors, and family memory stories, returning ranked results with matching context snippets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Full-Stack Local Technology Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: React 18, TypeScript, Vite, Tailwind CSS, Lucide Icons, and Web Audio API for in-browser audio capture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Python 3.10+, FastAPI, Pydantic v2, SQLite (for zero-config relational storage), Pytest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: Zero external dependencies. Controlled with 1-line startup scripts (&lt;code&gt;.\scripts\start.ps1&lt;/code&gt; or &lt;code&gt;./scripts/start.sh&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Open innovation is not just a developer preference for Grandma's Kitchen—it is a fundamental requirement. Here is why open-source AI was irreplaceable for this project:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Privacy &amp;amp; Data Sovereignty for Intimate Family Heritage
&lt;/h3&gt;

&lt;p&gt;Voice messages are uniquely personal. They contain non-verbal emotional nuances, family names, home locations, and vocal biometrics. Handing over decades of intimate family voice recordings to proprietary cloud APIs exposes personal heritage to remote server logs, third-party data breaches, and AI training pipelines. Open-weight models (Whisper and Llama) allow families to retain &lt;strong&gt;100% local control&lt;/strong&gt; over their data.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Preserving Qualitative &amp;amp; Cultural Cooking Nuances
&lt;/h3&gt;

&lt;p&gt;Proprietary cloud LLMs are heavily RLHF-tuned toward standard Western commercial outputs. When given informal spoken text, closed models tend to "autocorrect" cultural recipes into standard cookbook formulas—converting a &lt;em&gt;pinch&lt;/em&gt; into &lt;em&gt;1/4 tsp&lt;/em&gt; or dropping regional term names. Open models allow custom prompts and open-source fine-tuning that respect qualitative cooking language, family idioms, and regional traditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Zero Cost &amp;amp; Decade-Long Permanence
&lt;/h3&gt;

&lt;p&gt;Family heirlooms should last for generations. Relying on closed SaaS APIs introduces monthly subscription fees, API pricing changes, and vendor shutdown risks. By building on open-source AI running on local hardware, Grandma's Kitchen costs &lt;strong&gt;$0/month&lt;/strong&gt; to run and will remain functional 10 or 20 years from now, completely independent of cloud service lifecycles.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Reproducibility &amp;amp; Community Empowerment
&lt;/h3&gt;

&lt;p&gt;Because every component of this stack relies on open weights and open-source software, any family or developer worldwide can clone &lt;a href="https://github.com/scha54/Hactoberfest-Weekend-Challenge" rel="noopener noreferrer"&gt;our GitHub repository&lt;/a&gt;, run a single setup script, and immediately build a private memory vault for their own loved ones. &lt;/p&gt;

&lt;p&gt;Open innovation turns technology from a locked walled garden into a living tool for human connection and cultural preservation.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Thank you for reading! Feel free to check out the &lt;a href="https://github.com/scha54/Hactoberfest-Weekend-Challenge" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt; and share how you preserve your family's recipes and stories.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Canon Keeper: Reconciling Troublesome Lore</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Wed, 30 Sep 2026 07:12:57 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/canon-keeper-reconciling-troublesome-lore-654</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/canon-keeper-reconciling-troublesome-lore-654</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/sanity-2026-09-16"&gt;Sanity Challenge, Path One: Ship an Agent That Queries Real Content&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;CanonKeeper&lt;/strong&gt; is an AI-powered Fictional Universe Lore &amp;amp; Canon Resolution Engine. &lt;/p&gt;

&lt;p&gt;When building expansive fictional universes (fantasy novels, sci-fi series, tabletop RPGs, or gaming franchises), lore accumulated over years frequently suffers from &lt;strong&gt;retcons, timeline contradictions, bardic folklore myths, and multi-hop custody chains&lt;/strong&gt;. Traditional keyword search fails when an early edition book claims a commander entered a citadel in 734, but a later primary garrison ledger signed by the commander proves he remained at a northern outpost until 735.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CanonKeeper&lt;/strong&gt; solves this by storing structured lore documents in Sanity CMS and running an intelligent Lore Verification Agent that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queries atomic claims, source documents, characters, events, and locations via Sanity GROQ &amp;amp; MCP.&lt;/li&gt;
&lt;li&gt;Applies &lt;strong&gt;Source Authority Hierarchy Weighting&lt;/strong&gt; (&lt;code&gt;PRIMARY_CANON&lt;/code&gt; &amp;gt; &lt;code&gt;OFFICIAL_SECONDARY&lt;/code&gt; &amp;gt; &lt;code&gt;REFERENCE&lt;/code&gt; &amp;gt; &lt;code&gt;COMMUNITY&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Automatically detects and resolves &lt;strong&gt;Timeline Retcons&lt;/strong&gt; (e.g., 1st Edition Chronicles vs. Imperial Garrison Ledgers &amp;amp; Revised Edition).&lt;/li&gt;
&lt;li&gt;Performs &lt;strong&gt;Multi-Hop Evidence Deduction&lt;/strong&gt; to trace artifact possession and event chains across dates.&lt;/li&gt;
&lt;li&gt;Renders an &lt;strong&gt;Interactive SVG Evidence Graph&lt;/strong&gt; mapping nodes (&lt;code&gt;Question&lt;/code&gt;, &lt;code&gt;Claim&lt;/code&gt;, &lt;code&gt;Source&lt;/code&gt;, &lt;code&gt;Verdict&lt;/code&gt;) and directed relationship edges (&lt;code&gt;retrieves&lt;/code&gt;, &lt;code&gt;supported_by&lt;/code&gt;, &lt;code&gt;contradicts&lt;/code&gt;, &lt;code&gt;supersedes&lt;/code&gt;, &lt;code&gt;resolves_to&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Watch the complete video walkthrough of CanonKeeper in action:&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Video Link&lt;/strong&gt;: &lt;a href="https://youtu.be/Qoc_rMhq9z4" rel="noopener noreferrer"&gt;https://youtu.be/Qoc_rMhq9z4&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Check out the full open-source codebase on GitHub:&lt;/p&gt;

&lt;p&gt;🐙 &lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/scha54/Sanity-MCP-Hackathon" rel="noopener noreferrer"&gt;https://github.com/scha54/Sanity-MCP-Hackathon&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Sanity served as the structured graph foundation for CanonKeeper's knowledge base.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Structured Schema Modeling
&lt;/h3&gt;

&lt;p&gt;I designed 5 custom Sanity document schemas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;claim&lt;/code&gt;&lt;/strong&gt;: Represents atomic lore facts with subject-predicate-object triples, &lt;code&gt;source&lt;/code&gt; reference, &lt;code&gt;canonStatus&lt;/code&gt; (&lt;code&gt;CANON&lt;/code&gt;, &lt;code&gt;RETCONNED&lt;/code&gt;, &lt;code&gt;DISPUTED&lt;/code&gt;, &lt;code&gt;AMBIGUOUS&lt;/code&gt;), timeline markers, confidence scores, and reference arrays for &lt;code&gt;contradicts&lt;/code&gt;, &lt;code&gt;corroborates&lt;/code&gt;, and &lt;code&gt;supersedes&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;source&lt;/code&gt;&lt;/strong&gt;: Documents with &lt;code&gt;sourceType&lt;/code&gt; (&lt;code&gt;CHRONICLE&lt;/code&gt;, &lt;code&gt;MANUSCRIPT&lt;/code&gt;, &lt;code&gt;BARDIC_SONG&lt;/code&gt;, &lt;code&gt;LEDGER&lt;/code&gt;), &lt;code&gt;edition&lt;/code&gt;, &lt;code&gt;publicationDate&lt;/code&gt;, &lt;code&gt;authorityLevel&lt;/code&gt;, and &lt;code&gt;supersedes&lt;/code&gt; / &lt;code&gt;supersededBy&lt;/code&gt; references.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;character&lt;/code&gt;&lt;/strong&gt;: Character entities with aliases, descriptions, first appearance references, and typed relationships.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;event&lt;/code&gt;&lt;/strong&gt;: Chronological events with location references, participants, and preceding/following event links.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;location&lt;/code&gt;&lt;/strong&gt;: World locations linked to associated characters and events.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Sanity Model Context Protocol (MCP) Integration
&lt;/h3&gt;

&lt;p&gt;I configured the Sanity Model Context Protocol (MCP) server integration (&lt;code&gt;https://mcp.sanity.io&lt;/code&gt;) in &lt;code&gt;.agents/mcp_config.json&lt;/code&gt;. This enables AI agents to inspect schema types and query content via standardized MCP tool calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. GROQ Evidence Queries &amp;amp; Resolution Logic
&lt;/h3&gt;

&lt;p&gt;The agent retrieves evidence from Sanity using GROQ queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*[_type == "claim"]{
  _id,
  statement,
  subject,
  predicate,
  object,
  "sourceId": source._ref,
  sourceLocation,
  canonStatus,
  timeline,
  confidence,
  "contradictIds": contradicts[]._ref,
  "corroborateIds": corroborates[]._ref,
  "supersedeIds": supersedes[]._ref,
  notes
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What the agent does with retrieved Sanity content:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Entity &amp;amp; Intent Recognition&lt;/strong&gt;: Extracts entities (e.g., &lt;em&gt;Arin Shadowstrider&lt;/em&gt;, &lt;em&gt;Valemont Citadel&lt;/em&gt;) and timeframe constraints from user queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph Traversal&lt;/strong&gt;: Fetches matched claims, resolves linked &lt;code&gt;source&lt;/code&gt; document authority levels, and expands &lt;code&gt;contradicts&lt;/code&gt; / &lt;code&gt;supersedes&lt;/code&gt; graph nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authority &amp;amp; Retcon Resolution&lt;/strong&gt;: Overrides outdated claims when a higher authority document (e.g., &lt;code&gt;PRIMARY_CANON&lt;/code&gt; revised ledger) supersedes an earlier &lt;code&gt;OFFICIAL_SECONDARY&lt;/code&gt; account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Visualization&lt;/strong&gt;: Constructs node-link network graphs displaying claims, sources, and canon verdicts.&lt;/li&gt;
&lt;/ol&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;demo-universe&lt;/code&gt; &lt;em&gt;(Local fallback &amp;amp; Sanity dataset ready)&lt;/em&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;Seeding Script&lt;/strong&gt;: Included at &lt;a href="https://github.com/scha54/Sanity-MCP-Hackathon/blob/main/scripts/seed-sanity.ts" rel="noopener noreferrer"&gt;&lt;code&gt;scripts/seed-sanity.ts&lt;/code&gt;&lt;/a&gt; to populate Sanity CMS datasets using &lt;code&gt;@sanity/client&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>sanitychallenge</category>
      <category>sanity</category>
      <category>ai</category>
    </item>
    <item>
      <title>Beyond DOM Scraping: Building "THE LAST TERMINAL" with WebMCP</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Wed, 02 Sep 2026 18:54:48 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/beyond-dom-scraping-building-the-last-terminal-with-webmcp-42d6</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/beyond-dom-scraping-building-the-last-terminal-with-webmcp-42d6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Project Title&lt;/strong&gt;: &lt;strong&gt;THE LAST TERMINAL — WebMCP Escape Room&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/scha54/WebMCP" rel="noopener noreferrer"&gt;https://github.com/scha54/WebMCP&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://webmcp-blush.vercel.app/" rel="noopener noreferrer"&gt;https://webmcp-blush.vercel.app/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. Executive Summary &amp;amp; The Problem with Web Agents Today
&lt;/h2&gt;

&lt;p&gt;For the past several years, autonomous browser agents have interacted with web applications primarily through &lt;strong&gt;DOM scraping and visual inspection&lt;/strong&gt;. A typical AI browser workflow involves taking high-resolution screenshots, feeding them into a Vision-Language Model (VLM), predicting pixel coordinates or CSS selectors, and firing synthetic click and keypress events.&lt;/p&gt;

&lt;p&gt;This approach suffers from critical flaws:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fragility&lt;/strong&gt;: Minor CSS or markup refactors instantly break agent workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Inefficiency&lt;/strong&gt;: Uploading multiple high-res DOM trees and screenshots consumes tens of thousands of LLM tokens per action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency&lt;/strong&gt;: Visual feedback loops take seconds per step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ambiguity&lt;/strong&gt;: Agents must "guess" button intents without formal input parameter types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;WebMCP (Web Model Context Protocol)&lt;/strong&gt; is an emerging browser standard that solves this. Instead of forcing AI agents to reverse-engineer visual UIs, WebMCP allows web applications to directly register machine-readable &lt;strong&gt;tools&lt;/strong&gt; (&lt;code&gt;navigator.modelContext.registerTool&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;To demonstrate this paradigm shift, we built &lt;strong&gt;THE LAST TERMINAL&lt;/strong&gt;—a polished, browser-based cyberpunk escape room where human players and AI agents collaborate to solve interconnected facility puzzles using shared WebMCP tool capabilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. System Architecture: The Shared Business Logic Principle
&lt;/h2&gt;

&lt;p&gt;The core architectural principle behind &lt;strong&gt;THE LAST TERMINAL&lt;/strong&gt; is &lt;strong&gt;Unified Execution Logic&lt;/strong&gt;. The application never duplicates business logic for human interactions vs. agent interactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 ┌──────────────────────────┐
                 │     WEBMCP AGENT /       │
                 │     DEMO SIMULATOR       │
                 └────────────┬─────────────┘
                              │
                      WebMCP Tool Calls
                              │
                              ▼
 ┌───────────────────────────────────────────────────────────┐
 │                   THE LAST TERMINAL                       │
 │                                                           │
 │  ┌─────────────────────────────────────────────────────┐  │
 │  │                 src/lib/webmcp/                     │  │
 │  │   tools.ts · schemas.ts · registry.ts              │  │
 │  └──────────────────────────┬──────────────────────────┘  │
 │                             │                             │
 │                             ▼                             │
 │  ┌─────────────────────────────────────────────────────┐  │
 │  │                  src/lib/game/                      │  │
 │  │   gameEngine.ts · gameState.ts · puzzles.ts         │  │
 │  └─────────────┬─────────────────────────┬─────────────┘  │
 │                │                         │                │
 │                ▼                         ▼                │
 │  ┌───────────────────────────┐ ┌───────────────────────┐  │
 │  │     Human Visual UI       │ │   Agent Activity      │  │
 │  │  (Facility Map &amp;amp; Systems) │ │   &amp;amp; Tool Trace Log    │  │
 │  └───────────────────────────┘ └───────────────────────┘  │
 └───────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a human user flips physical switches on the Power Control UI, the component triggers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;restorePower&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;C&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;A&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;D&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;B&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;human&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;p&gt;When an AI agent invokes the WebMCP tool &lt;code&gt;restore_power&lt;/code&gt;, the WebMCP execution context routes directly to the identical function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;restorePower&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;C&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;A&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;D&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;B&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;agent&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;p&gt;Both invocations mutate the central &lt;code&gt;GameState&lt;/code&gt;, trigger real-time UI updates, emit Web Audio synthesized feedback, and push a structured entry to the &lt;strong&gt;Agent Activity Feed&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. WebMCP Tool Suite (10 Exposed Capabilities)
&lt;/h2&gt;

&lt;p&gt;The application exposes 10 structured tools representing realistic facility subsystems:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Tool Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;JSON Input Schema&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;get_game_state&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieves system lock statuses, discovered clues, and active view&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;inspect_system&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Inspects facility subsystems (&lt;code&gt;security&lt;/code&gt;, &lt;code&gt;power&lt;/code&gt;, &lt;code&gt;archive&lt;/code&gt;, etc.)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "system": "surveillance" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;read_log&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reads facility logs by ID (&lt;code&gt;LOG-2049&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "logId": "LOG-2049" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;inspect_surveillance&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Inspects CCTV camera feeds (&lt;code&gt;CAM-07&lt;/code&gt;) for frame anomalies&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "cameraId": "CAM-07" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;decode_message&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Decodes encrypted ciphers into override candidates&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "message": "SURVEILLANCE_ANOMALY" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;restore_power&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Restores auxiliary power using quad-switch sequence&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "sequence": ["C", "A", "D", "B"] }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unlock_security&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unlocks security terminal with 4-digit passcode&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "code": "7319" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;code&gt;open_archive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mounts archive database vault (requires auxiliary power)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;code&gt;inspect_archive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Queries archive records matching search terms&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "query": "exit protocol" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unlock_exit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Disengages emergency exit pneumatic doors&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "code": "7319" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  JSON Schema &amp;amp; Code Example: &lt;code&gt;restore_power&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESTORE_POWER_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ordered list of switch labels, e.g. ["C", "A", "D", "B"].&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;required&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="s1"&gt;sequence&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;additionalProperties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// WebMCP Tool Definition&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;restore_power&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Attempt to restore auxiliary power grid using an ordered 4-switch sequence.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RESTORE_POWER_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;restorePower&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="nx"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&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;h2&gt;
  
  
  4. Prerequisite-Driven State Machine
&lt;/h2&gt;

&lt;p&gt;WebMCP tools should not be omnipotent "cheat codes." To demonstrate realistic agent reasoning, tools enforce environment prerequisites:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;openArchive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ToolCallSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;agent&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="c1"&gt;// Prerequisite Guard&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;currentGameState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;power&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PREREQUISITE_NOT_MET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Facility archive requires auxiliary power. Restore power first.&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="nf"&gt;recordToolCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open_archive&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&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;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;currentGameState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;archive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unlocked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ... state progression&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an agent attempts &lt;code&gt;open_archive()&lt;/code&gt; while power is offline, WebMCP returns a structured JSON error response code &lt;code&gt;PREREQUISITE_NOT_MET&lt;/code&gt;. The agent reads this structured output, inspects logs to discover that power must be restored, and calls &lt;code&gt;restore_power&lt;/code&gt; first.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. WebMCP Tool Registration &amp;amp; Browser Hydration
&lt;/h2&gt;

&lt;p&gt;To register tools safely in React environments without re-registering on component re-renders, &lt;strong&gt;THE LAST TERMINAL&lt;/strong&gt; implements an initialization guard module in &lt;code&gt;src/lib/webmcp/registry.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;initialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerWebMCPTools&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;boolean&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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;initialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isWebMCPAvailableInBrowser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Polyfill window.__webmcp for browser inspection and agent simulators&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;__webmcp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WEBMCP_TOOLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;WEBMCP_TOOLS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&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;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&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="nx"&gt;source&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="c1"&gt;// Native WebMCP Imperative API&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nav&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&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;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelContext&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerTool&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;function&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="nx"&gt;WEBMCP_TOOLS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;agent&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="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;isWebMCPAvailableInBrowser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;initialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Failed to register WebMCP tools:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&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="nx"&gt;isWebMCPAvailableInBrowser&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;h2&gt;
  
  
  6. Live Agent Activity Feed &amp;amp; Execution Trace Inspector
&lt;/h2&gt;

&lt;p&gt;For hackathon judges and developers, transparency is vital. The interface provides two real-time inspection features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Agent Activity Feed&lt;/strong&gt;: A live terminal log rendering request/response flow:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   23:51:04  AGENT  → inspect_surveillance("CAM-07")
   23:51:05  SYSTEM ← clue discovered: 7319
   23:51:09  AGENT  → unlock_security("7319")
   23:51:09  SYSTEM ← SECURITY UNLOCKED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Full Agent Trace Modal&lt;/strong&gt;: A complete JSON log inspector displaying timestamps, source identifiers (&lt;code&gt;human&lt;/code&gt;, &lt;code&gt;agent&lt;/code&gt;, &lt;code&gt;simulator&lt;/code&gt;), JSON inputs, return objects, and execution durations.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  7. Zero-Dependency Audio &amp;amp; UI Polish
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Web Audio API Synthesizer&lt;/strong&gt;: Uses standard browser &lt;code&gt;AudioContext&lt;/code&gt; to generate retro cyberpunk typing clicks, success chimes, failure buzzers, and power-up sweeps without hosting external MP3 files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demo Agent Simulator&lt;/strong&gt;: Provides a 90-second deterministic agent automated execution mode so judges can experience the full room walkthrough without requiring external AI API keys or specialized browser extensions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Setup, Testing &amp;amp; Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Repository Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/scha54/WebMCP.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WebMCP
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running Tests
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run isolated Game Engine test suite&lt;/span&gt;
npm run &lt;span class="nb"&gt;test&lt;/span&gt;:engine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Production Build &amp;amp; Vercel
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Next.js static build check&lt;/span&gt;
npm run build

&lt;span class="c"&gt;# Deploy to Vercel&lt;/span&gt;
vercel &lt;span class="nt"&gt;--prod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. Conclusion: The Future of Agentic Web Interfaces
&lt;/h2&gt;

&lt;p&gt;WebMCP transforms web applications from passive visual UIs into &lt;strong&gt;agentic APIs&lt;/strong&gt;. By exposing structured tools alongside standard visual components, websites become directly operable by AI models with 90%+ token reduction and near-zero latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;THE LAST TERMINAL&lt;/strong&gt; proves that building WebMCP-compatible web apps is clean, robust, and framework-agnostic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check out the source code on &lt;a href="https://github.com/scha54/WebMCP" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Explore the live demo and test the WebMCP tools yourself!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>antigravity</category>
      <category>ai</category>
      <category>webmcp</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>LifeOps: Delegating Outcomes, Not Checklists</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Mon, 31 Aug 2026 18:56:55 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/lifeops-delegating-outcomes-not-checklists-d55</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/lifeops-delegating-outcomes-not-checklists-d55</guid>
      <description>&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/scha54/All-Things-Agentic-Hackathon" rel="noopener noreferrer"&gt;https://github.com/scha54/All-Things-Agentic-Hackathon&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Technology Stack:&lt;/strong&gt; Google ADK, Gemini API, Python, FastAPI, SQLite, React, TypeScript, Vite&lt;/p&gt;


&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;Most personal AI tools today operate as passive text synthesizers. When faced with a complex life event—such as relocating to a new apartment—users are forced to manage an exhausting checklist: reading contract terms, notifying utility vendors, scheduling installation technicians, reserving movers, updating addresses, and tracking deadlines. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LifeOps&lt;/strong&gt; introduces a paradigm shift in personal software engineering: &lt;strong&gt;Outcome Delegation&lt;/strong&gt;. Instead of prompting an assistant for step-by-step instructions, the user delegates a high-level outcome: &lt;em&gt;"Sort out my broadband and apartment move situation."&lt;/em&gt; LifeOps autonomously investigates available documents, constructs a task dependency graph, executes low-risk background actions, pauses deterministically for human approval on high-risk operations, monitors progress asynchronously, and verifies completion against provider APIs.&lt;/p&gt;

&lt;p&gt;This article details the design, agent hierarchy, risk guardrails, verification loops, and zero-cloud local deployment architecture of LifeOps.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. The Architectural Shift: Chatbot vs. Autonomous Operations Agent
&lt;/h2&gt;

&lt;p&gt;Traditional AI interactions follow a synchronous request-response loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CHATBOT PARADIGM:
User  ───►  Question ("How do I cancel my internet?")  ───►  LLM  ───►  Advice Text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LifeOps transforms this into an event-driven operational workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LIFEOPS AUTONOMOUS PARADIGM:
User
 │
 ▼
Delegate Outcome ("Move my internet and apartment services")
 │
 ├──► Discovery Agent (Inspects lease &amp;amp; bill PDFs, extracts dates &amp;amp; policy constraints)
 ├──► Planning Agent (Constructs 7-step task dependency graph)
 ├──► Execution Agent (Submits utility notices, queries technician slots)
 ├──► Risk Engine (Pauses HIGH-risk booking for Human Approval)
 ├──► Verification Agent (Queries provider DB to confirm booking)
 ├──► Event Monitor (Detects vendor cancellation ──► Autonomously Replans ──► Rebooks)
 │
 ▼
✓ LIFE OPERATION RESOLVED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Multi-Agent Orchestration with Google ADK
&lt;/h2&gt;

&lt;p&gt;LifeOps is engineered around the &lt;strong&gt;Google ADK (Agent Development Kit v2.3.0)&lt;/strong&gt; framework. Rather than inflating agent counts for cosmetic appeal, every agent fulfills a distinct operational role:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    User([User Outcome Input]) --&amp;gt; API[FastAPI Server]
    API --&amp;gt; Orchestrator[Orchestrator Agent]

    Orchestrator --&amp;gt; DB[(Local SQLite DB)]
    Orchestrator --&amp;gt; Discovery[Discovery Agent]
    Orchestrator --&amp;gt; Planner[Planning Agent]
    Orchestrator --&amp;gt; Execution[Execution Agent]

    Execution --&amp;gt; DocAgent[Document Agent]
    Execution --&amp;gt; ResearchAgent[Research Agent]
    Execution --&amp;gt; CommAgent[Communication Agent]

    Execution --&amp;gt; Verification[Verification Agent]

    Verification --&amp;gt; DB
    Orchestrator --&amp;gt; RiskEngine[Deterministic Risk Engine]
    RiskEngine --&amp;gt; ApprovalRequest{Human Sign-Off Needed?}
    ApprovalRequest -- Yes --&amp;gt; Pause[Pause &amp;amp; Queue Approval]
    Pause --&amp;gt; UI[Command Center UI]
    UI -- Approve --&amp;gt; Resume[Resume &amp;amp; Verify]&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  Specialist Agent Responsibilities:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Orchestrator Agent&lt;/strong&gt;: Maintains overall workflow state, step transitions, risk evaluations, and paused state recovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discovery Agent&lt;/strong&gt;: Inspects local document vaults (&lt;code&gt;current_lease.txt&lt;/code&gt;, &lt;code&gt;new_lease.txt&lt;/code&gt;, &lt;code&gt;internet_bill.txt&lt;/code&gt;, &lt;code&gt;utility_bill.txt&lt;/code&gt;) and extracts structured facts with confidence ratings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Planning Agent&lt;/strong&gt;: Builds task graphs with explicit parent-child dependency bindings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution Agent&lt;/strong&gt;: Interacts with mock digital provider APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Agent&lt;/strong&gt;: Extracts lease dates, notice windows, and contract penalties.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research Agent&lt;/strong&gt;: Scans provider slots and compares pricing options.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication Agent&lt;/strong&gt;: Drafts formal move-out notices and vendor emails (enforcing strict separation between &lt;code&gt;DRAFT&lt;/code&gt; and &lt;code&gt;SEND&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification Agent&lt;/strong&gt;: Queries mock system databases to confirm outcome states rather than blindly trusting tool output.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. Deterministic Safety: The Human-in-the-Loop Risk Engine
&lt;/h2&gt;

&lt;p&gt;A major failure mode in modern agentic systems is allowing LLMs to execute irreversible financial or legal actions without boundary controls. LifeOps solves this by enforcing a deterministic, application-level &lt;strong&gt;Risk Engine&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;Action Name&lt;/th&gt;
&lt;th&gt;Risk Level&lt;/th&gt;
&lt;th&gt;Action Taken&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;read_document&lt;/code&gt;, &lt;code&gt;extract_facts&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;LOW&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-Executed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;query_provider_api&lt;/code&gt;, &lt;code&gt;check_slots&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;LOW&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-Executed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;draft_email&lt;/code&gt;, &lt;code&gt;send_notification&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MEDIUM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-Executed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;request_internet_transfer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MEDIUM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-Executed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;book_moving_company&lt;/code&gt; (Cost: ₹12,500)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;HIGH&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PAUSES WORKFLOW — Requires Approval&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;book_broadband_installation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;HIGH&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PAUSES WORKFLOW — Requires Approval&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;financial_transaction&lt;/code&gt;, &lt;code&gt;cancel_contract&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CRITICAL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PAUSES WORKFLOW — Requires Approval&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When an action triggers &lt;code&gt;HIGH&lt;/code&gt; or &lt;code&gt;CRITICAL&lt;/code&gt; risk (or involves financial expenditure), LifeOps pauses the workflow, emits an &lt;code&gt;APPROVAL_REQUESTED&lt;/code&gt; event, and presents a structured card to the user containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What&lt;/strong&gt;: The proposed action&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: The financial commitment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt;: Operational rationale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence&lt;/strong&gt;: Document sources &amp;amp; quotes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controls&lt;/strong&gt;: &lt;code&gt;[Approve &amp;amp; Resume]&lt;/code&gt; or &lt;code&gt;[Reject]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Asynchronous Resilience &amp;amp; Self-Healing Event Replanning
&lt;/h2&gt;

&lt;p&gt;LifeOps state is stored in a local SQLite database (&lt;code&gt;lifeops.db&lt;/code&gt;) configured with Write-Ahead Logging (WAL) for concurrency. If the application or machine restarts mid-operation, LifeOps inspects unfulfilled workflows and resumes idempotent tasks without duplicating actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Wow Moment": Vendor Cancellation Recovery
&lt;/h3&gt;

&lt;p&gt;During the primary demo scenario, a simulated external emergency occurs: &lt;em&gt;SwiftShift Movers cancels the moving booking due to vehicle breakdown.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;LifeOps reacts autonomously:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Event Reception&lt;/strong&gt;: Listens to mock system webhooks (&lt;code&gt;EXTERNAL_EVENT_RECEIVED&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Transition&lt;/strong&gt;: Marks the original movers task as &lt;code&gt;CANCELLED&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autonomous Replanning&lt;/strong&gt;: Wakes up, triggers the &lt;strong&gt;Research Agent&lt;/strong&gt; to query replacement options (&lt;em&gt;Metro Express Logistics&lt;/em&gt; at ₹11,500), and generates a new approval request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign-Off &amp;amp; Verification&lt;/strong&gt;: Once approved, books the replacement and verifies the confirmation code in the provider database.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  5. Local-First, No-GCP Compliance Architecture
&lt;/h2&gt;

&lt;p&gt;To ensure strict privacy and developer accessibility, LifeOps operates 100% locally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero Cloud Infrastructure&lt;/strong&gt;: 0 dependencies on Cloud Run, Firestore, Pub/Sub, Vertex AI, or Secret Manager.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct Model Inference&lt;/strong&gt;: Connects directly to the Gemini API (&lt;code&gt;gemini-3.5-flash&lt;/code&gt; / &lt;code&gt;gemini-2.5-flash&lt;/code&gt;) via &lt;code&gt;GEMINI_API_KEY&lt;/code&gt; stored in &lt;code&gt;.env&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Audit Tool&lt;/strong&gt;: Includes &lt;code&gt;scripts/check_no_gcp.py&lt;/code&gt; to audit the repository for prohibited cloud imports or hardcoded keys.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LifeOps Infrastructure Audit
=============================================
Google ADK:       PASS
Gemini API:       PASS (Managed via local .env)
GCP Services:     NONE DETECTED
Secret Leaks:     CLEAN (0 hardcoded keys in source)
SQLite:           PASS
Local Scheduler:  PASS
=============================================
Result: PASSED (NO-GCP &amp;amp; CLEAN SECRETS)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Repository &amp;amp; Setup Instructions
&lt;/h2&gt;

&lt;p&gt;The full working source code is available on GitHub:&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/scha54/All-Things-Agentic-Hackathon" rel="noopener noreferrer"&gt;https://github.com/scha54/All-Things-Agentic-Hackathon&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Running Locally:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clone &amp;amp; Configure Environment&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/scha54/All-Things-Agentic-Hackathon.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;All-Things-Agentic-Hackathon
   &lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
   &lt;span class="c"&gt;# Add your GEMINI_API_KEY to .env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialize Database&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   python scripts/init_db.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start Mock Digital World (Port 8001)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   python mock_world/server.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start FastAPI Backend (Port 8000)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   python &lt;span class="nt"&gt;-m&lt;/span&gt; uvicorn backend.app.main:app &lt;span class="nt"&gt;--reload&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start React Dashboard&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run Audits &amp;amp; Tests&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   python scripts/check_no_gcp.py
   python &lt;span class="nt"&gt;-m&lt;/span&gt; unittest discover backend/tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Conclusion
&lt;/h2&gt;

&lt;p&gt;LifeOps proves that personal AI can transcend conversational chat boxes to become true autonomous operations centers. By pairing &lt;strong&gt;Google ADK&lt;/strong&gt; multi-agent orchestration and &lt;strong&gt;Gemini&lt;/strong&gt; document intelligence with deterministic risk guardrails and local SQLite persistence, LifeOps delivers a secure, privacy-preserving solution where users delegate outcomes and software handles the operational heavy lifting.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>antigravity</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>Cooking with CSS: Coding 'One More Bite' — The Steaming Comfort Food Oracle</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Sun, 16 Aug 2026 19:56:23 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/cooking-with-css-coding-one-more-bite-the-steaming-comfort-food-oracle-16o6</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/cooking-with-css-coding-one-more-bite-the-steaming-comfort-food-oracle-16o6</guid>
      <description>&lt;p&gt;This is a submission for Frontend Challenge - Comfort Food Edition, CSS Art._&lt;/p&gt;

&lt;p&gt;Inspiration&lt;br&gt;
When thinking about comfort food, we didn't want to design another generic, calorie-counting recipe database. We wanted to capture the emotional warmth of food—the quiet feeling of sitting in a sun-drenched digital kitchen at golden hour.&lt;/p&gt;

&lt;p&gt;Our CSS and SVG art was inspired by:&lt;/p&gt;

&lt;p&gt;The Steaming Golden-Hour Soup Bowl: A centerpiece illustration on the landing page representing immediate warmth. It features hand-crafted SVG elements, custom CSS floating spice particles (drifting at varying speeds), and rising steam lines.&lt;br&gt;
The Dynamic Hunger Bowl: An interactive piece of SVG art tied to our custom hunger slider. As you slide from "Just peckish" to "Feed me immediately", the bowl physically expands, fills up with colorful broth (shifting from soft peach to deep tomato red), and populates with ingredients like tofu blocks, sliced carrots, green scallions, and hot steam.&lt;br&gt;
The visual theme uses an editorial cream-paper texture, soft espresso typography, and organic card borders to feel like a handwritten note from a close friend.&lt;/p&gt;

&lt;p&gt;Demo&lt;br&gt;
Here is a preview of the interactive comfort food experience:&lt;/p&gt;

&lt;p&gt;One More Bite Interactive Demo&lt;/p&gt;

&lt;p&gt;GitHub Repository: scha54/One-More-Bite&lt;br&gt;
Journey&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setting up Tailwind CSS v4 and Vite
We initialized a clean React + TypeScript project and integrated the new Tailwind CSS v4 plugin. Tailwind v4's CSS-first theme configuration allowed us to set up our warm, cozy palette variables directly in src/index.css using standard theme directives:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;css&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/theme"&gt;@theme&lt;/a&gt; {&lt;br&gt;
  --font-serif: "Fraunces", Georgia, serif;&lt;br&gt;
  --font-sans: "Manrope", sans-serif;&lt;br&gt;
  --color-cream: #FAF5EC;&lt;br&gt;
  --color-paper: #FFFDF9;&lt;br&gt;
  --color-espresso: #2D221C;&lt;br&gt;
  --color-terracotta: #C85A3C;&lt;br&gt;
  --color-saffron: #EAA93E;&lt;br&gt;
  --color-olive: #6E7753;&lt;br&gt;
  --color-peach: #EBB99D;&lt;br&gt;
}&lt;br&gt;
We layered an inline base64 SVG fractal noise pattern on the body tag to establish a warm, tactile paper parchment background texture without incurring external asset load costs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Building the Interactive CSS/SVG Art
The highlights of the implementation are the micro-interactions:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Hunger Slider: We built a custom slider track. We intercepted the range input onChange event in React, updating a scale factor and content rendering arrays. The SVG tofu, carrot, and scallion vectors are conditionally rendered based on hunger levels 1 through 4.&lt;br&gt;
The Reveal pay-off Loader: The transition from the quiz to the result spins a golden plate SVG using a slow linear animation keyframe, while rapidly cycling comfort food names inside. This creates a playful, rewarding anticipation loop before displaying your match.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Personalization &amp;amp; The Addictive Recommendation Loop&lt;br&gt;
We coded a local, client-side recommendation engine that weighs candidate scores using your cuisine, emotional state, and hunger level. To build a delightful repeat loop, we implemented a "One More Bite" button. This passes an array of previously matched IDs to our engine, executing an exclusions filter so that clicking it rolls a new compatible recommendation (e.g. transitioning from Masala Dosa to Moong Dal Khichdi or Rajma Chawal on the same selections) with a fresh transition animation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accessibility as a Core Feature&lt;br&gt;
Rather than treating accessibility as an afterthought, we ensured:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The progress indicator lists screen-reader hidden text descriptions (Question 2 of 3).&lt;br&gt;
Visible focus ring offsets outline all select buttons and sliders when tabbing.&lt;br&gt;
A media query listener immediately overrides and halts all rotating plates, floating spice particles, and rising steam lines if a user prefers reduced motion:&lt;br&gt;
css&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/media"&gt;@media&lt;/a&gt; (prefers-reduced-motion: reduce) {&lt;br&gt;
  .animate-steam, .animate-float-slow, .animate-spin-slow {&lt;br&gt;
    animation: none !important;&lt;br&gt;
    transform: none !important;&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
This project reminded us that focusing on polish, smooth transitions, and visual storytelling is often far more rewarding than adding complex databases and unnecessary backends. Sometimes, a beautiful static frontend is exactly what you need.&lt;/p&gt;

&lt;p&gt;Made with 🧡 for DEV Community.&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
      <category>ai</category>
    </item>
    <item>
      <title>PawPrint: Unleashing AI-Powered RPG Dog Cards with Gemini 2.5 Flash 🐾</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Sun, 16 Aug 2026 14:46:53 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/pawprint-unleashing-ai-powered-rpg-dog-cards-with-gemini-25-flash-1d0j</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/pawprint-unleashing-ai-powered-rpg-dog-cards-with-gemini-25-flash-1d0j</guid>
      <description>&lt;p&gt;This is a submission for Weekend Challenge: Dog Days Edition&lt;/p&gt;

&lt;p&gt;What I Built&lt;br&gt;
PawPrint is a web application that lets dog owners transform their real-life furry companions into fully playable, custom RPG character cards!&lt;/p&gt;

&lt;p&gt;By uploading a photo of their pup and taking a quick personality quiz (covering habits like where they sleep, how they react to the doorbell, or their behavior on walks), users can forge high-fidelity RPG cards. The app generates:&lt;/p&gt;

&lt;p&gt;RPG Class: Including archetypes like Bark Mage, Treat Paladin, Nap Rogue, and Chaos Ranger.&lt;br&gt;
Rarity: Grading from Common, Uncommon, Rare, Epic, up to Legendary.&lt;br&gt;
Stats: HP, Attack, Defense, and Speed based on the quiz questions and card rarity.&lt;br&gt;
Unique Abilities: Fun, class-specific active, passive, and ultimate abilities with comedic lore descriptions.&lt;br&gt;
Weaknesses &amp;amp; Backstories: Tailored backstory bios explaining their origin and a hilarious weakness (like "The Dreaded Vacuum Cleaner" or "Baths").&lt;br&gt;
Beyond card generation, the app features:&lt;/p&gt;

&lt;p&gt;Persistent Deck Roster: Keep track of all generated dogs, stored offline in the browser's localStorage.&lt;br&gt;
Deck Management: Full search and sorting controls (by name, breed, date, and stats), and filters by RPG Class or Rarity.&lt;br&gt;
Interactive Battle Arena: A turn-based combat simulator where you can duel two dogs, or test your dog's mettle against built-in legendary AI bosses like Sir Mailman (Letter Knight) or The Dreaded Vacuum (Chaos Devourer).&lt;br&gt;
Instant Card Sharing: Share individual dogs using encoded query-string URLs (?card=...) that allow other users to view and import the card with a single click.&lt;br&gt;
Theme Support: Seamless toggle between sleek dark and clean light modes.&lt;br&gt;
Demo&lt;br&gt;
You can try the live app here: PawPrint Live Site (Replace this with your actual deployed URL!)&lt;/p&gt;

&lt;p&gt;(To see it in action without configuring an API key, the app runs in local Demo Mode with a deterministic rule-based generator!)&lt;/p&gt;

&lt;p&gt;Code&lt;br&gt;
The project is fully open-source and hosted on GitHub: &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/scha54" rel="noopener noreferrer"&gt;
        scha54
      &lt;/a&gt; / &lt;a href="https://github.com/scha54/Pawprint" rel="noopener noreferrer"&gt;
        Pawprint
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Vibe coded this application with Antigravity and Gemini for the Dev.to Weekend Challenge
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🐾 PawPrint RPG Card Generator&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;PawPrint is an AI-powered tabletop RPG character card generator for dog owners. By uploading a photo of their dog and answering a short personality quiz, users can forge a high-fidelity RPG card complete with customized stats, unique abilities, comedic weaknesses, and a custom lore backstory.&lt;/p&gt;

&lt;p&gt;The project features a client-side implementation of the Google Gemini API, a persistent roster of saved cards, and an interactive Battle Arena where dogs can face off against each other or challenge legendary AI opponents.&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ Features&lt;/h2&gt;
&lt;/div&gt;


&lt;ul&gt;

&lt;li&gt;

&lt;strong&gt;🧙‍♂️ Personality Quiz&lt;/strong&gt;: 5 interactive questions to gauge your dog's temperament (sleeping style, doorbell response, walks behavior, etc.) which influence their statistics and RPG class.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;🎨 AI-Powered Card Forging&lt;/strong&gt;: Analyzes the dog's picture and personality questions using &lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt; (or a fallback offline simulator) to generate names, breeds, class, rarity, abilities, and origin stories.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;💾 Persistent Deck Roster&lt;/strong&gt;: Cards…&lt;/li&gt;

&lt;/ul&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/scha54/Pawprint" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;
 (Or visit the repository directly at github.com/scha54/Pawprint)

&lt;p&gt;How I Built It&lt;br&gt;
🛠️ The Tech Stack&lt;br&gt;
Framework: React 19 + TypeScript + Vite (for lightning-fast HMR and type-safety)&lt;br&gt;
Styling: Tailwind CSS v4 + Vanilla CSS Custom Tokens (enabling easy light/dark mode configuration)&lt;br&gt;
AI Core: Google Generative AI SDK (@google/generative-ai)&lt;br&gt;
Icons: Lucide React&lt;br&gt;
Exporting: html-to-image (allowing users to download their cards as PNG images)&lt;br&gt;
Testing: Vitest (for core game logic and storage helper tests)&lt;br&gt;
🧠 Google Gemini Integration&lt;br&gt;
PawPrint relies on the Google Generative AI SDK, querying the Gemini 2.5 Flash model directly from the client. When a user submits their pup's photo and quiz answers, we build a multimodal prompt:&lt;/p&gt;

&lt;p&gt;Multimodal Inputs: We pass the compressed image base64 data and the options chosen during the quiz.&lt;br&gt;
Structured JSON Output: To make the generation reliable, we utilize the SDK's responseMimeType: 'application/json' configuration, forcing Gemini to respond with a JSON payload that perfectly fits our TypeScript DogCharacter interface. This eliminates the need for messy string parsing or regex matching.&lt;br&gt;
Local Mock Fallback: In the absence of an API key, we wrote an offline character engine (src/services/gemini.ts) that uses the quiz options' mathematical modifiers to calculate stats, choose classes, and assign preset abilities—providing a seamless demo mode experience.&lt;br&gt;
💾 Canvas Image Compression&lt;br&gt;
Because we want cards to persist in browser storage, we had to solve a major limitation: localStorage is capped at roughly 5MB. Standard mobile phone photos are often 3MB–10MB, which would immediately crash the storage. To solve this, the ImageUploader component loads uploaded images into an HTML5  element, downscales them to a maximum boundary of 500px (preserving aspect ratio), and encodes them as a JPEG with a quality factor of 0.85. This compresses the base64 string to just 20–50KB, allowing users to save dozens of cards effortlessly.&lt;/p&gt;

&lt;p&gt;⚔️ turn-Based Battle Engine&lt;br&gt;
The Battle Arena simulator uses a custom deterministic scoring system (src/utils/scoring.ts):&lt;/p&gt;

&lt;p&gt;Turn Order: The dog with the highest Speed stat acts first.&lt;br&gt;
Elemental Advantages: We coded a rock-paper-scissors class advantage system: Bark Mage beats Treat Paladin -&amp;gt; Treat Paladin beats Nap Rogue -&amp;gt; Nap Rogue beats Chaos Ranger -&amp;gt; Chaos Ranger beats Bark Mage. A class advantage boosts final damage by 25%.&lt;br&gt;
Combat Logic: Turn damage is calculated as (Attack / (Defense * 0.8)) * 15 * advantage. Round 1 triggers passive abilities, subsequent rounds utilize basic pounces, and dropping below 40% health triggers massive ultimate moves!&lt;br&gt;
Prize Categories&lt;br&gt;
This project is submitted for:&lt;/p&gt;

&lt;p&gt;Best Use of Google AI: Featuring a clean client-side implementation of the Gemini 2.5 Flash model with the official @google/generative-ai SDK. It demonstrates the strength of multimodal prompts (image + text) combined with structured JSON outputs, showing how developers can leverage Gemini to build immersive, interactive gamified experiences in a lightweight serverless frontend.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>ai</category>
      <category>antigravity</category>
    </item>
    <item>
      <title>Build a Production-Grade AI Dashboard: Architectural Insights from the BMW AutoTrend Platform</title>
      <dc:creator>Sandeep Chakravartty</dc:creator>
      <pubDate>Sat, 01 Aug 2026 11:06:02 +0000</pubDate>
      <link>https://dev.to/sandeep_chakravartty_219e/build-a-production-grade-ai-dashboard-architectural-insights-from-the-bmw-autotrend-platform-4hg2</link>
      <guid>https://dev.to/sandeep_chakravartty_219e/build-a-production-grade-ai-dashboard-architectural-insights-from-the-bmw-autotrend-platform-4hg2</guid>
      <description>&lt;p&gt;&lt;em&gt;Orchestrating Clean Architecture, Subprocess Scrapers, SQLite FTS5, and Local LLMs (Ollama) inside a Dockerized Python + React Stack.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Executive Summary &amp;amp; Design Goals
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;BMW AutoTrend Dashboard&lt;/strong&gt; is a local-first, AI-powered automotive intelligence platform that scrapes, processes, classifies, and visualizes market trends and sentiment for BMW-related news. The system is designed to run completely locally, using a local LLM instance via &lt;strong&gt;Ollama&lt;/strong&gt; for article summarization and entity extraction, backed up by a deterministic rule-based regex fallback engine.&lt;/p&gt;

&lt;p&gt;The platform was built with the following design goals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clean Architecture&lt;/strong&gt;: Decouple the data extraction layer, storage mechanism, analytical computations, and API controllers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Fallbacks&lt;/strong&gt;: Ensure the application remains fully functional (using a rule-based regex processor) even when local LLM resources (Ollama) are offline or resource-constrained.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local-First &amp;amp; High Performance&lt;/strong&gt;: Use &lt;strong&gt;SQLite FTS5&lt;/strong&gt; for instant full-text search, keeping all scraped data, search indexes, and analysis files stored locally without external SaaS API dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plug-and-Play Extensibility&lt;/strong&gt;: Allow plugging in new scraping adapters (e.g., Autoblog, MotorTrend) by implementing a unified abstract interface.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  2. Clean System Architecture
&lt;/h2&gt;

&lt;p&gt;The application adheres to &lt;strong&gt;Clean Architecture&lt;/strong&gt; principles, maintaining a strict unidirectional data flow and isolating business logic from external dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    subgraph Frontend [React SPA - Served via Nginx]
        UI[Interactive Dashboard Pages]
        RC[Recharts Visualizations]
        FTS_UI[Spotlight Search UI]
    end

    subgraph Backend [FastAPI Application]
        API[FastAPI Endpoints]
        SCH[APScheduler Ingestion &amp;amp; Snapshots]
        ING[Ingestion Pipeline]
        ANA[Analytics Engine]
        AIP[AI Processing Pipeline]
    end

    subgraph CLI Bridge [Subprocess Execution]
        WBC[Webcmd CLI + BMWBLOG Plugin]
    end

    subgraph Storage [Local Storage]
        DB[(SQLite Database)]
        FTS[(FTS5 Search Index)]
    end

    subgraph Local LLM [AI Inference]
        OLL[Ollama Server]
    end

    UI --&amp;gt;|Queries| API
    API --&amp;gt;|Reads/Writes| DB
    ING --&amp;gt;|Executes| WBC
    WBC --&amp;gt;|Scrapes Web Data| BMWBLOG[BMWBLOG Site]
    ING --&amp;gt;|Sends content for classification| AIP
    AIP --&amp;gt;|Requests JSON| OLL
    AIP --&amp;gt;|Regex Fallback| AIP
    SCH --&amp;gt;|Triggers| ING
    SCH --&amp;gt;|Runs daily| ANA
    ANA --&amp;gt;|Computes stats| DB
    FTS_UI --&amp;gt;|Queries FTS| API
    API --&amp;gt;|FTS Match Query| FTS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend Layer&lt;/strong&gt;: A React + TypeScript SPA built with Vite. It interacts with the backend strictly via standardized JSON REST endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Controllers&lt;/strong&gt;: FastAPI handlers that validate schemas using Pydantic, query storage, and trigger background tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core Business Logic&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Ingestion Pipeline&lt;/strong&gt; orchestrates scraping, duplicate checks, and data ingestion.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;AI Processing Pipeline&lt;/strong&gt; performs text analysis, summarization, and tag extraction.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Analytics Engine&lt;/strong&gt; aggregates metrics and maintains daily snapshots.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Providers&lt;/strong&gt;: Subprocess wrappers encapsulating the execution of Node.js-based CLI tools (&lt;code&gt;webcmd&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Layer&lt;/strong&gt;: SQLite managed via SQLAlchemy ORM, enriched with raw SQL database triggers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Ingestion Pipeline &amp;amp; Subprocess WebCMD Scraping
&lt;/h2&gt;

&lt;p&gt;Data ingestion begins with the abstract base class &lt;code&gt;NewsProvider&lt;/code&gt; in [providers/base.py]. Concrete providers, such as the &lt;code&gt;BMWBlogProvider&lt;/code&gt; in &lt;a&gt;providers/bmwblog.py&lt;/a&gt;, are responsible for crawling data from publishers.&lt;/p&gt;

&lt;p&gt;Rather than writing custom web scrapers that are brittle and hard to maintain, the backend utilizes the &lt;code&gt;@agentrhq/webcmd&lt;/code&gt; CLI tool under the hood. The &lt;code&gt;BMWBlogProvider&lt;/code&gt; executes &lt;code&gt;webcmd&lt;/code&gt; as a subprocess to retrieve structured article feeds.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Subprocess Execution Mechanism
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# snippet from backend/providers/bmwblog.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_run_webcmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;webcmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# We use shell=True on Windows because webcmd is a script (.ps1 or .cmd)
&lt;/span&gt;        &lt;span class="n"&gt;is_windows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;is_windows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CalledProcessError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;webcmd execution failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;webcmd error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pipeline executes in two stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Metadata Fetching&lt;/strong&gt;: Runs &lt;code&gt;webcmd bmwblog latest -f json&lt;/code&gt; to retrieve the latest 10 articles (metadata only: URLs, titles, brief excerpts).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep Article Ingestion&lt;/strong&gt;: For each &lt;em&gt;new&lt;/em&gt; URL (determined by checking the SQLite index), it queries &lt;code&gt;webcmd bmwblog article &amp;lt;url&amp;gt; -f json&lt;/code&gt; to extract the full body text, category, author, and scrapes the raw HTML for OpenGraph images (&lt;code&gt;og:image&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  4. Hybrid AI Classification Pipeline (Ollama &amp;amp; Regex Fallbacks)
&lt;/h2&gt;

&lt;p&gt;Once full article text is ingested, it is dispatched to &lt;a&gt;ai/processor.py&lt;/a&gt;. The processor uses a hybrid system that dynamically checks Ollama's availability before selecting an evaluation engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    A[New Article Ingested] --&amp;gt; B{Is Ollama Server Online?}
    B --&amp;gt;|Yes| C[Call Ollama Llama 3.2 API]
    C --&amp;gt; D{Parsing JSON Successful?}
    D --&amp;gt;|Yes| E[Save AI Classification to Database]
    D --&amp;gt;|No| F[Fallback to Regex Rule Engine]
    B --&amp;gt;|No| F
    F --&amp;gt; G[Extract Entities, Sentiment, &amp;amp; Summaries via Rules]
    G --&amp;gt; E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Ollama LLM Pipeline
&lt;/h3&gt;

&lt;p&gt;If the Ollama server is online and running &lt;code&gt;llama3.2&lt;/code&gt;, the backend posts to &lt;code&gt;/api/generate&lt;/code&gt; with a carefully crafted prompt. To ensure deterministic integration, the request forces a structured JSON output:&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="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OLLAMA_MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stream&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;options&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&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;The model classifies sentiment (Positive, Neutral, Negative), extracts relevant vehicle models (e.g., &lt;em&gt;Neue Klasse&lt;/em&gt;, &lt;em&gt;BMW M3&lt;/em&gt;), maps technology tags (e.g., &lt;em&gt;Battery Technology&lt;/em&gt;, &lt;em&gt;ADAS&lt;/em&gt;), and generates short, detailed, and TL;DR summaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Rule-Based Regex Fallback Pipeline
&lt;/h3&gt;

&lt;p&gt;If Ollama is offline (or fails to return valid JSON), &lt;code&gt;_analyze_with_rules&lt;/code&gt; executes. It uses pre-compiled regular expressions to match keywords and tags:&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="n"&gt;TECHNOLOGY_TAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Electric Vehicles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(ev|evs|electric|zero-emission|zero emission|battery electric|bev)\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Battery Technology&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(battery|batteries|solid-state|cell|cells|rimac)\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Autonomous Driving&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(autonomous|self-driving|driverless|autopilot)\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Sentiment heuristic based on term tallying
&lt;/span&gt;&lt;span class="n"&gt;pos_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;rf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;combined_text&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;SENTIMENT_POSITIVE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;neg_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;rf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;combined_text&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;SENTIMENT_NEGATIVE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This hybrid model guarantees that database columns are populated with valid categories and tags, and that search capabilities are never compromised by hardware limitations.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. High-Performance SQLite FTS5 Search Indexing with Database Triggers
&lt;/h2&gt;

&lt;p&gt;For high-speed, local-first search, the project bypasses slow &lt;code&gt;LIKE %query%&lt;/code&gt; SQL operations and utilizes SQLite's native &lt;strong&gt;FTS5 (Full-Text Search)&lt;/strong&gt; extension. &lt;/p&gt;

&lt;h3&gt;
  
  
  Database Schema Initialization and Triggers
&lt;/h3&gt;

&lt;p&gt;In &lt;a&gt;database/connection.py&lt;/a&gt;, the application boots the database using SQLAlchemy, but hooks into standard connection events to enforce foreign key constraints (&lt;code&gt;PRAGMA foreign_keys=ON&lt;/code&gt;) and manually provisions an FTS5 virtual table + synchronization triggers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- FTS5 Virtual Table Configuration&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;VIRTUAL&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;articles_fts&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;fts5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'articles'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Synchronization Triggers (Insert, Delete, Update)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TRIGGER&lt;/span&gt; &lt;span class="n"&gt;articles_ai&lt;/span&gt; &lt;span class="k"&gt;AFTER&lt;/span&gt; &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="k"&gt;BEGIN&lt;/span&gt;
    &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;articles_fts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rowid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These triggers offload search indexing directly to the SQLite engine. Whenever a new article is committed via SQLAlchemy, SQLite automatically indexes the title, excerpt, and content inside the FTS5 shadow tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relevance-Based Search Endpoint
&lt;/h3&gt;

&lt;p&gt;When a user searches the dashboard, the backend performs a BM25 relevance-ranking query:&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="c1"&gt;# Snippet from backend/api/routes.py
&lt;/span&gt;&lt;span class="n"&gt;query_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    SELECT rowid FROM articles_fts 
    WHERE articles_fts MATCH :query
    ORDER BY bm25(articles_fts)
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_str&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;search_term&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This executes in sub-milliseconds, giving the frontend instantaneous "Search-as-you-type" capabilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Dynamic Analytics Engine &amp;amp; Rolling Trend Computations
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Analytics Engine&lt;/strong&gt; in &lt;a&gt;analytics/engine.py&lt;/a&gt; performs rolling window calculations to determine which automotive trends are gaining traction.&lt;/p&gt;

&lt;p&gt;Instead of tracking basic counts, the engine computes a &lt;strong&gt;weekly growth rate&lt;/strong&gt; by comparing mentions of vehicle models and technologies over a rolling 7-day window vs the preceding 7-day window.&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="c1"&gt;# 7-day boundaries
&lt;/span&gt;&lt;span class="n"&gt;seven_days_ago&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;today_start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fourteen_days_ago&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;today_start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Mentions in last 7 days (recent) vs 7-14 days ago (previous)
# Growth calculation:
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prev_cnt&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="n"&gt;growth_pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;recent_cnt&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;growth_pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;recent_cnt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;prev_cnt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;prev_cnt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting topics are sorted by &lt;code&gt;growth_rate DESC&lt;/code&gt; to populate the "Trending Topics" widgets in the UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Historical Snapshotting
&lt;/h3&gt;

&lt;p&gt;To prevent CPU-heavy aggregations every time a user loads the page, the application uses &lt;strong&gt;APScheduler&lt;/strong&gt; to execute &lt;code&gt;generate_daily_snapshot&lt;/code&gt; near midnight. This function serializes the calculated statistics to JSON and stores it in the &lt;code&gt;analytics_snapshots&lt;/code&gt; table, enabling fast rendering of historical timelines over 30 days.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Frontend Architecture (React + Vite + Recharts)
&lt;/h2&gt;

&lt;p&gt;The frontend is a single-page application built on a modern React + TypeScript + Vite architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Glassmorphic Theme&lt;/strong&gt;: A premium dark-mode interface built on CSS variables, custom Outfit typography, and glowing borders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component Layout&lt;/strong&gt;: The sidebar and main panels are structured in &lt;code&gt;layouts/DashboardLayout.tsx&lt;/code&gt; for responsive navigation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visualizations&lt;/strong&gt;: Uses &lt;code&gt;Recharts&lt;/code&gt; to display dynamic data:

&lt;ul&gt;
&lt;li&gt;Area charts for daily article volumes.&lt;/li&gt;
&lt;li&gt;Sentiment timelines mapping Positive/Neutral/Negative trends over a 30-day period.&lt;/li&gt;
&lt;li&gt;Bar charts comparing vehicle model and technology tag popularity.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Search&lt;/strong&gt;: Ingests keypresses, queries the SQLite FTS5 index via the API, and highlights matches with sub-millisecond lag.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Docker Orchestration &amp;amp; DevSecOps Insights
&lt;/h2&gt;

&lt;p&gt;The platform is designed to launch with a single command: &lt;code&gt;docker compose up --build&lt;/code&gt;. The orchestration configures three networks-isolated, dependent containers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ollama Container&lt;/strong&gt;: Pulls and serves LLM models on port &lt;code&gt;11434&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI Backend Container&lt;/strong&gt;: Built from &lt;code&gt;docker/backend.Dockerfile&lt;/code&gt;. It maps the database to a persistent Docker volume &lt;code&gt;db_data&lt;/code&gt; at &lt;code&gt;/app/data/autotrend.db&lt;/code&gt; so database records are saved permanently across container restarts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx Frontend Container&lt;/strong&gt;: A multi-stage build that compiles the React application and uses Nginx to serve the static assets on port &lt;code&gt;80&lt;/code&gt;, proxying requests to the backend.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Technical Docker Tip: Node.js Subprocess Requirement
&lt;/h3&gt;

&lt;p&gt;Since the python backend invokes &lt;code&gt;webcmd&lt;/code&gt; (an npm library) as a subprocess, the backend Dockerfile must be configured to support a multi-runtime environment. Adding Node.js, &lt;code&gt;npm&lt;/code&gt;, and installing &lt;code&gt;@agentrhq/webcmd&lt;/code&gt; globally inside the python slim container ensures the ingestion pipeline compiles without error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Install Node.js, NPM, and global webcmd CLI scraper&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    build-essential curl gnupg &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://deb.nodesource.com/setup_20.x | bash - &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nodejs &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @agentrhq/webcmd &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; webcmd plugin &lt;span class="nb"&gt;install &lt;/span&gt;github:agentrhq/webcmd/bmwblog &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. Extensibility &amp;amp; Future Scope
&lt;/h2&gt;

&lt;p&gt;The design of the AutoTrend Dashboard makes it easily expandable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adding New News Outlets&lt;/strong&gt;: Create a new class implementing the &lt;code&gt;NewsProvider&lt;/code&gt; abstract base class (e.g. &lt;code&gt;AutoblogProvider&lt;/code&gt;). Map the scraper plugin commands (e.g. &lt;code&gt;webcmd autoblog latest&lt;/code&gt;), and register the provider in &lt;code&gt;run_ingestion_pipeline&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External LLMs&lt;/strong&gt;: The AI client in [ai/client.py] can be extended to support remote cloud models (such as the Gemini API or OpenAI API) using environment variables for API keys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced Sentiment Heuristics&lt;/strong&gt;: The rule-based engine can be upgraded to support VADER or transformer models (like Hugging Face's &lt;code&gt;distilbert-base-uncased-finetuned-sst-2-english&lt;/code&gt;) for deep offline sentiment extraction.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Created as technical documentation for the BMW AutoTrend Dashboard codebase.Github Repo at &lt;a href="https://github.com/scha54/BMW-AutoTrend-Dashboard" rel="noopener noreferrer"&gt;https://github.com/scha54/BMW-AutoTrend-Dashboard&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webcmd</category>
      <category>ai</category>
      <category>antigravity</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
