<?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: Khe Ai</title>
    <description>The latest articles on DEV Community by Khe Ai (@kheai).</description>
    <link>https://dev.to/kheai</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%2F789591%2F20f5f929-80e6-456f-b891-efb5be57c07a.jpeg</url>
      <title>DEV Community: Khe Ai</title>
      <link>https://dev.to/kheai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kheai"/>
    <language>en</language>
    <item>
      <title>Connecting RooCode to Gemma4-26B-MoE via OpenAI Bridge</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Tue, 02 Jun 2026 17:33:01 +0000</pubDate>
      <link>https://dev.to/kheai/connecting-roocode-to-gemma4-26b-moe-via-openai-bridge-koi</link>
      <guid>https://dev.to/kheai/connecting-roocode-to-gemma4-26b-moe-via-openai-bridge-koi</guid>
      <description>&lt;p&gt;This configuration bypasses extension UI limitations by routing direct Google AI Studio requests through Google’s native OpenAI-compliant endpoint. This allows you to use newly released or unlisted models like &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; completely free of charge, without needing a third-party proxy account like OpenRouter.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code&lt;/strong&gt; with the &lt;strong&gt;RooCode&lt;/strong&gt; extension installed.
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Google AI Studio API Key&lt;/strong&gt; (Get one for free at &lt;a href="https://aistudio.google.com/?authuser=1" rel="noopener noreferrer"&gt;aistudio.google.com&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. RooCode Profile Configuration
&lt;/h2&gt;

&lt;p&gt;Open your RooCode settings menu (the gear icon at the top right of the extension pane) and fill out the fields exactly as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Setting&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Value to Enter&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Provider&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;OpenAI Compatible&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Standardizes data transport to match Google's bridge.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Base URL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://generativelanguage.googleapis.com/v1beta/openai/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Must include the trailing slash (&lt;code&gt;/&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Key&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Your Google AI Studio API Key&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Starts with &lt;code&gt;AIzaSy...&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The exact technical identifier for the model.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model Reasoning Effort&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;None&lt;/code&gt; / &lt;code&gt;Default&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Not natively supported by Gemma models; leave it blank or default.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Why This Works (Troubleshooting Context)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Bridge Endpoint:&lt;/strong&gt; Google provides the &lt;code&gt;/v1beta/openai/&lt;/code&gt; URL block specifically so developers can drop Gemini models seamlessly into software written for OpenAI backends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bypassing Dropdowns:&lt;/strong&gt; Choosing "OpenAI Compatible" instructs RooCode to treat the &lt;strong&gt;Model&lt;/strong&gt; box as a free-form text input rather than a strict, predefined dropdown menu, preventing the extension from stripping out unlisted models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Tool Calling:&lt;/strong&gt; RooCode requires full tool-calling support to write code and read files in your editor. Because &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; supports native function calling out of the box via this bridge, RooCode's autonomous agent actions function normally.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro-Tip:&lt;/strong&gt; If Google updates this model line in the future (e.g., to a newer point release), you only need to swap out the text string in the &lt;strong&gt;Model&lt;/strong&gt; field without changing any other parameters.&lt;/p&gt;

</description>
      <category>gemma</category>
      <category>kheai</category>
      <category>vscode</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Why Build a Startup If Not for Money?</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Tue, 02 Jun 2026 14:19:35 +0000</pubDate>
      <link>https://dev.to/kheai/why-build-a-startup-if-not-for-money-5cb6</link>
      <guid>https://dev.to/kheai/why-build-a-startup-if-not-for-money-5cb6</guid>
      <description>&lt;h3&gt;
  
  
  The Unspoken Playbook of the Sovereign Creator
&lt;/h3&gt;

&lt;p&gt;For decades, the dominant narrative around startups has been hyper-fixated on one metric: the exit. We are conditioned to view entrepreneurship through the lens of venture capital, hockey-stick growth charts, and generational wealth.&lt;/p&gt;

&lt;p&gt;But what happens when you remove financial gain from the primary equation? If you aren't doing it to buy a yacht or retire early, why on earth would you willingly subject yourself to the volatility, sleepless nights, and staggering failure rates of building something from scratch?&lt;/p&gt;

&lt;p&gt;When you strip away the financial incentive, you don't find passivity. Instead, you uncover the purest, most resilient forms of human drive. Here is what I have learned about what actually happens when you build a startup for everything &lt;em&gt;except&lt;/em&gt; the money—and why it might just be the ultimate way to live.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Reality Check: The Luxury of "Not Caring" About Capital
&lt;/h2&gt;

&lt;p&gt;Let’s be brutally honest and set a skeptical anchor right out of the gate: &lt;strong&gt;building a startup without prioritizing money is an act of immense privilege.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are struggling to pay rent or feed your family, the profit motive isn't just healthy; it is mandatory. But once you achieve baseline financial security—or if you choose to live a radically low-overhead lifestyle ("ramen profitable")—something fascinating happens to your decision-making matrix.&lt;/p&gt;

&lt;p&gt;When you optimize for revenue above all else, you are forced to make concessions. You build features you hate because a enterprise client demanded them. You chase trends because that’s where the VC funding is flowing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When money is no longer your master, &lt;strong&gt;compromise drops to zero.&lt;/strong&gt; You gain the rarest asset in modern business: absolute alignment between your values and your output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. The Scratch You Cannot Stop Clawing (Obsessive Problem-Solving)
&lt;/h2&gt;

&lt;p&gt;Most people encounter a broken system, a terrible piece of software, or an inefficient workflow and think, &lt;em&gt;"Wow, that sucks,"&lt;/em&gt; before moving on with their day.&lt;/p&gt;

&lt;p&gt;But a specific subset of people suffer from what I call a "splinter in the mind." A broken reality agitates them. When you aren't building for money, you turn into a pure &lt;strong&gt;problem-solver&lt;/strong&gt;. You aren't scanning the market for "lucrative gaps"; you are dead-set on fixing a specific piece of the universe that is currently broken.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Shift in Focus
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Venture-Backed Mindset:&lt;/strong&gt; "Is the Total Addressable Market (TAM) big enough to justify an IPO?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Sovereign Mindset:&lt;/strong&gt; "Does this solution need to exist in the world? Will it fundamentally improve the day-to-day existence of the people who use it?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This obsession creates a massive competitive advantage. When a profit-driven founder hits a wall where the financial ROI turns negative, they pivot or quit. When &lt;em&gt;you&lt;/em&gt; hit that same wall, you keep digging because your return on investment isn't measured in dollars—it’s measured in the eradication of the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Hacker-Artist Paradigm: Pure Creation as an Antidote to Existential Dread
&lt;/h2&gt;

&lt;p&gt;There is a distinct joy in writing a clean line of code, designing an intuitive user interface, or crafting a seamless user experience. It is the joy of the artisan.&lt;/p&gt;

&lt;p&gt;Somewhere along the line, the tech world forgot that software engineering and company building are deeply creative acts. They are modern forms of art.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[The Industrial Loop]  → Produce for Consumption → Optimize for Scale  → Erase the Artisan&lt;/li&gt;
&lt;li&gt;[The Sovereign Loop]   → Build for the Sake of It → Optimize for Beauty → Preserves the Soul&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you build without the sole goal of monetization, you treat your startup like a canvas. You build things simply because they are beautiful, elegant, or intellectually stimulating. This is the ethos that built the early open-source movement and the early internet. It’s the desire to say, &lt;em&gt;"I was here, and I shaped this small corner of reality according to my own aesthetic."&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Autonomy Premium: Buying Back Your Sovereignty
&lt;/h2&gt;

&lt;p&gt;Corporate life is an exercise in managed compromise. You trade your time and your creative control for predictable compensation.&lt;/p&gt;

&lt;p&gt;For many of us, the true alternative to a startup isn't wealth—it’s &lt;strong&gt;sovereignty&lt;/strong&gt;. Building a project outside the traditional corporate matrix allows you to establish a micro-ecosystem that answers to no one but you and your users.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No arbitrary KPIs:&lt;/strong&gt; You don't have to hit fake metrics to please a board of directors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No political theater:&lt;/strong&gt; You don't waste 40% of your energy managing upwards or dealing with bureaucratic red tape.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Radical collaboration:&lt;/strong&gt; You choose exactly who you work with, ensuring that every teammate or user shares your specific wavelength.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You aren't trying to build an empire; you are trying to build a fortress that protects your personal freedom and intellectual peace.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Turning Life into a High-Fidelity Simulator
&lt;/h2&gt;

&lt;p&gt;Let’s face a hard truth: comfort breeds stagnation. If you don't need money, the easiest thing to do is sit back, consume content, and let your brain atrophy in a state of passive leisure.&lt;/p&gt;

&lt;p&gt;But passive leisure is a psychological trap that frequently leads to existential dread. Human beings are evolutionary engines designed to overcome friction.&lt;/p&gt;

&lt;p&gt;A startup is the ultimate high-fidelity simulator for personal growth. It tests every single dimension of your capability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intellectual:&lt;/strong&gt; You must master copywriting, system architecture, psychology, and legal frameworks simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emotional:&lt;/strong&gt; You have to deal with public criticism, bugs that break your system at 2:00 AM, and the vulnerability of putting your work out into the world.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Philosophical:&lt;/strong&gt; It forces you to constantly answer the question: &lt;em&gt;What is actually worth my limited time on this planet?&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By treating entrepreneurship as an elite sport rather than a financial transaction, the startup becomes a forcing function to turn you into the sharpest, most resilient version of yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary: The Post-Financial Playbook
&lt;/h2&gt;

&lt;p&gt;If someone asks you why you are pouring your life blood into a project that might never make you rich, show them this framework.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;The Conventional Startup&lt;/th&gt;
&lt;th&gt;The Sovereign Project&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Metric&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Valuation &amp;amp; MRR (Monthly Recurring Revenue)&lt;/td&gt;
&lt;td&gt;Autonomy &amp;amp; Utility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scale Strategy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hyper-growth, often unsustainable&lt;/td&gt;
&lt;td&gt;Sustainable, often "One-Man" or micro-team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Success State&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An acquisition or IPO&lt;/td&gt;
&lt;td&gt;An evergreen tool that runs flawlessly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relationship to Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monetizable data or traffic units&lt;/td&gt;
&lt;td&gt;A community of like-minded peers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Building without chasing money isn't aimless hobbyism. It is a highly disciplined, deeply intentional way to reclaim your time, express your creativity, and solve real-world problems on your own terms.&lt;/p&gt;

&lt;p&gt;Stop asking if it scales. Stop asking how it monetizes. &lt;strong&gt;Just build things that should exist.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>kheai</category>
      <category>startup</category>
      <category>sideprojects</category>
      <category>career</category>
    </item>
    <item>
      <title>Building a Decentralized Content Pipeline with Nostr &amp; Astro</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Tue, 02 Jun 2026 07:36:04 +0000</pubDate>
      <link>https://dev.to/kheai/building-a-decentralized-content-pipeline-with-nostr-astro-5341</link>
      <guid>https://dev.to/kheai/building-a-decentralized-content-pipeline-with-nostr-astro-5341</guid>
      <description>&lt;p&gt;I recently deployed my fully decentralized content pipeline to &lt;a href="https://www.kheai.com" rel="noopener noreferrer"&gt;kheai.com&lt;/a&gt; (you can check out the source code at &lt;code&gt;github.com/kafechew/nostr-seo&lt;/code&gt;). After rigorously testing the architecture, I wanted to document exactly how this system works. We are not just building a blog; we are engineering an evergreen, censorship-resistant Web3-to-Web2 bridge.&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/kafechew" rel="noopener noreferrer"&gt;
        kafechew
      &lt;/a&gt; / &lt;a href="https://github.com/kafechew/nostr-seo" rel="noopener noreferrer"&gt;
        nostr-seo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;⚡ Nostr-SEO: The Decentralized Content Bridge&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.kheai.com/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/23063cd2ddafe24ac99d461367aabbbacc0b5547ffff19110e6ac43d82d8fa46/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6976655f44656d6f2d6b686561692e636f6d2d3030433742373f7374796c653d666f722d7468652d6261646765" alt="Live Demo"&gt;&lt;/a&gt;
&lt;a href="https://astro.build/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/aee2410383a0c5c49033b8e1472bf7f9c9844cf9cc84a6170d0f0ba6efe72c20/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4275696c745f776974682d417374726f2d4646354430313f7374796c653d666f722d7468652d6261646765266c6f676f3d617374726f" alt="Built with Astro"&gt;&lt;/a&gt;
&lt;a href="https://nostr.com/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e45d8d3bf93c7e82f122d54edea8bf803b56fb349c40aed593b0c8f6781448a6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f77657265645f62792d4e6f7374722d3832343146383f7374796c653d666f722d7468652d6261646765" alt="Powered by Nostr"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nostr-SEO&lt;/strong&gt; is a high-performance, SEO-first bridge that transforms decentralized Nostr Long-form content (&lt;strong&gt;Kind 30023&lt;/strong&gt;) into a lightning-fast, search-engine-optimized website.&lt;/p&gt;
&lt;p&gt;Built on top of the refined &lt;a href="https://github.com/satnaing/astro-paper" rel="noopener noreferrer"&gt;Astro-Paper&lt;/a&gt; template, this project allows creators to use Nostr as a decentralized CMS while maintaining total ownership of their web presence and search engine rankings.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📖 The Problem &amp;amp; Solution&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;The Problem&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Decentralized protocols like Nostr are amazing for censorship resistance, but their content is often "invisible" to traditional search engines. If you publish only on relays, you lose the benefits of &lt;strong&gt;SEO (Search Engine Optimization)&lt;/strong&gt; and &lt;strong&gt;AEO (Answer Engine Optimization)&lt;/strong&gt; for AI agents like Perplexity and ChatGPT.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;The Solution&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;nostr-seo&lt;/code&gt; acts as a &lt;strong&gt;Static Site Generator (SSG) for the Nostr protocol&lt;/strong&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fetch:&lt;/strong&gt; It pulls your articles from decentralized relays at build-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process:&lt;/strong&gt; It cleans the Markdown, renders complex Math (LaTeX) and Diagrams (Mermaid).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy:&lt;/strong&gt; It…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kafechew/nostr-seo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;In this tutorial, you will build an automated pipeline that fetches your long-form articles from decentralized Nostr clients (like Yakihonne or Primal), converts them into a blazing-fast static website using Astro, and hosts it for free on Vercel.&lt;/p&gt;

&lt;p&gt;Zero prior Astro experience is required. If you follow these steps, you will go from an empty folder to a live, SEO-optimized prototype.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture Vision
&lt;/h2&gt;

&lt;p&gt;Before writing code, you must understand the data flow. We are shifting from a "push" model (saving files to a server) to a "pull" model (compiling decentralized data at build time).&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[Author on Yakihonne/Primal] --&amp;gt;|Publishes Kind 30023| B(Nostr Relays)
    C[GitHub Actions Cron] --&amp;gt;|Triggers Build every 6h| D(Vercel Edge Network)
    D --&amp;gt;|Fetches Data| B
    D --&amp;gt;|Compiles HTML/CSS| E[Your Live Website]
    E --&amp;gt; F[Human Readers]
    E --&amp;gt; G[AI Agents via llm.txt]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Tech Stack
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Component&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Tool&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nostr Protocol&lt;/td&gt;
&lt;td&gt;Decentralized content storage and syndication.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Framework&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Astro (AstroPaper)&lt;/td&gt;
&lt;td&gt;High-speed static site generation and routing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Processor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unified Ecosystem&lt;/td&gt;
&lt;td&gt;Parsing Markdown, KaTeX (math), and Mermaid (diagrams).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hosting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Vercel&lt;/td&gt;
&lt;td&gt;Edge delivery and automated webhooks.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Phase 0: The Digital Workbench
&lt;/h2&gt;

&lt;p&gt;You need a few standard tools installed before we begin.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download and install the &lt;strong&gt;LTS (Long Term Support)&lt;/strong&gt; version of Node.js from &lt;code&gt;nodejs.org&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Install Git from &lt;code&gt;git-scm.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Download Visual Studio Code, the industry-standard code editor.&lt;/li&gt;
&lt;li&gt;Create free accounts on GitHub and Vercel.&lt;/li&gt;
&lt;li&gt;Convert your Nostr &lt;code&gt;npub&lt;/code&gt; to a Hexadecimal key using a tool like &lt;code&gt;damus.io/key&lt;/code&gt;. Keep this Hex key safe; our code needs it to identify you on the network.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Phase 1: Local Setup &amp;amp; Installation
&lt;/h2&gt;

&lt;p&gt;Open your terminal. We will use the AstroPaper template as our foundation.&lt;/p&gt;

&lt;p&gt;Run the following command to download the template into a new folder named &lt;code&gt;nostr-seo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create astro@latest &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; satnaing/astro-paper nostr-seo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate into your new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;nostr-seo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we must install our communication tools (NDK for Nostr) and our processing engines (Unified for Markdown/Math). Run this command exactly as written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @nostr-dev-kit/ndk ws nostr-tools remark-math rehype-katex rehype-stringify remark-rehype remark-parse unified &lt;span class="nt"&gt;--legacy-peer-deps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: The &lt;code&gt;--legacy-peer-deps&lt;/code&gt; flag prevents npm from crashing if the Astro template's default formatting tools have strict version conflicts with our new parser.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The MacOS/Linux WebAssembly Patch
&lt;/h3&gt;

&lt;p&gt;If you are on an older OS, the build engine (&lt;code&gt;esbuild&lt;/code&gt;) might fail. Open your &lt;code&gt;package.json&lt;/code&gt; file and append these properties to force Node.js to bypass your core OS framework and use WebAssembly instead:&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;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esbuild-wasm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.28.0"&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;span class="nl"&gt;"overrides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esbuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:esbuild-wasm@0.28.0"&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;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;Open the project in your editor by typing &lt;code&gt;code .&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 2: Core Engineering &amp;amp; Data Pipelines
&lt;/h2&gt;

&lt;p&gt;Because we are fetching posts from Nostr relays rather than local &lt;code&gt;.md&lt;/code&gt; files, we must create a custom processing pipeline to handle rich text, math equations, and metadata.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: The Markdown Processor
&lt;/h3&gt;

&lt;p&gt;Create a new file at &lt;code&gt;src/utils/parseMarkdown.ts&lt;/code&gt;. This utility converts raw Nostr strings into safe, styled HTML.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;unified&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unified&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;remarkParse&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remark-parse&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;remarkMath&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remark-math&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;remarkRehype&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remark-rehype&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;rehypeKatex&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rehype-katex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;rehypeStringify&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rehype-stringify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parseNostrMarkdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;unified&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remarkParse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remarkMath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remarkRehype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rehypeKatex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rehypeStringify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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;h3&gt;
  
  
  Step 2: The Event Formatter
&lt;/h3&gt;

&lt;p&gt;Create a new file at &lt;code&gt;src/utils/formatNostrEvent.ts&lt;/code&gt;. This extracts SEO descriptions and generates proper &lt;code&gt;naddr&lt;/code&gt; links for cross-platform Web3 sharing.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nip19&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nostr-tools&lt;/span&gt;&lt;span class="dl"&gt;"&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;formatNostrEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&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="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="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)?.[&lt;/span&gt;&lt;span class="mi"&gt;1&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;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;findTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;summary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fallbackDesc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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;\[&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;?\]\(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;?\)&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="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;\[(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;?)\]\(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;?\)&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;$1&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;(?:&lt;/span&gt;&lt;span class="sr"&gt;__|&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;*#`&lt;/span&gt;&lt;span class="se"&gt;\[\]&lt;/span&gt;&lt;span class="sr"&gt;()&lt;/span&gt;&lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="sr"&gt;+!=&lt;/span&gt;&lt;span class="se"&gt;])&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="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;160&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="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;findTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;naddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&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="nx"&gt;naddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nip19&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;naddrEncode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dTag&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="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="s2"&gt;Naddr error&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;naddr&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;findTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Untitled&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="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;fallbackDesc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;pubDatetime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;modDatetime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;findTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nostr User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;t&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="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;t&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="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;ogImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;findTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;naddr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;naddr&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;
  
  
  Phase 3: Building the Interface
&lt;/h2&gt;

&lt;p&gt;We will hijack AstroPaper's default routing to dynamically pull your Kind 30023 events at build time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: The Homepage (&lt;code&gt;index.astro&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;code&gt;src/pages/index.astro&lt;/code&gt;. Delete everything and paste the code below. &lt;strong&gt;Replace the Hex string with your own public key.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import Layout from "@/layouts/Layout.astro";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import NDK, { type NDKEvent } from "@nostr-dev-kit/ndk";
import 'ws'; 

const ndk = new NDK({ 
  explicitRelayUrls: [
    "wss://relay.damus.io", 
    "wss://nos.lol",
    "wss://relay.primal.net"
  ] 
});

try {
  await ndk.connect(3000); 
} catch (err) {
  console.error("Nostr Connection failed:", err);
}

// REMEMBER TO INSERT YOUR HEX KEY BELOW
const filter = { 
  kinds: [30023], 
  authors: ["YOUR_HEX_PUBLIC_KEY_HERE"]
};

let events: Set&amp;lt;NDKEvent&amp;gt; = new Set();

try {
  const fetchPromise = ndk.fetchEvents(filter, { closeOnEose: true });
  const timeoutPromise = new Promise&amp;lt;Set&amp;lt;NDKEvent&amp;gt;&amp;gt;((resolve) =&amp;gt; {
    setTimeout(() =&amp;gt; resolve(new Set()), 4000);
  });

  events = await Promise.race([fetchPromise, timeoutPromise]);
} catch (err) {
  console.error("Fetch error:", err);
}

const posts = Array.from(events)
  .filter((e): e is NDKEvent &amp;amp; { created_at: number } =&amp;gt; e.created_at !== undefined)
  .sort((a, b) =&amp;gt; b.created_at - a.created_at)
  .map(e =&amp;gt; {
    const cleanContent = e.content.replace(/[#*`_~\[\]\(\)-]/g, "").replace(/\s+/g, " ").trim();
    return {
      id: e.id,
      title: e.tags.find((t: string[]) =&amp;gt; t[0] === 'title')?.[1] || "Untitled Post",
      summary: e.tags.find((t: string[]) =&amp;gt; t[0] === 'summary')?.[1] || (cleanContent.substring(0, 120) + "..."),
      date: new Date(e.created_at * 1000).toLocaleDateString('en-US', {
        year: 'numeric', month: 'long', day: 'numeric'
      })
    };
  });
---

&amp;lt;Layout title="My Decentralized Mind-Dump"&amp;gt;
  &amp;lt;Header /&amp;gt;
  &amp;lt;main id="main-content" class="app-layout"&amp;gt;
    &amp;lt;section id="hero" class="border-border border-b pt-8 pb-6"&amp;gt;
      &amp;lt;h1 class="my-4 inline-block text-4xl font-bold sm:my-8 sm:text-5xl"&amp;gt;My Nostr Mind-Dump&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;Pulled dynamically from the Nostr protocol at build time. Write on Web3, read everywhere.&amp;lt;/p&amp;gt;
    &amp;lt;/section&amp;gt;

    &amp;lt;section id="recent-posts" class="pt-12 pb-6"&amp;gt;
      &amp;lt;h2 class="text-2xl font-semibold tracking-wide mb-6"&amp;gt;Recent Notes&amp;lt;/h2&amp;gt;
      &amp;lt;ul&amp;gt;
        {posts.map(post =&amp;gt; (
          &amp;lt;li class="my-6"&amp;gt;
            &amp;lt;a href={`/nostr/${post.id}`} class="inline-block text-xl font-bold text-skin-accent decoration-dashed underline-offset-4 hover:underline"&amp;gt;
              {post.title}
            &amp;lt;/a&amp;gt;
            &amp;lt;div class="text-sm opacity-80 mt-1"&amp;gt;{post.date}&amp;lt;/div&amp;gt;
            &amp;lt;p class="mt-2 line-clamp-3"&amp;gt;{post.summary}&amp;lt;/p&amp;gt;
          &amp;lt;/li&amp;gt;
        ))}
      &amp;lt;/ul&amp;gt;
    &amp;lt;/section&amp;gt;
  &amp;lt;/main&amp;gt;
  &amp;lt;Footer /&amp;gt;
&amp;lt;/Layout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: The Article Reader Route
&lt;/h3&gt;

&lt;p&gt;Create a new folder named &lt;code&gt;nostr&lt;/code&gt; inside &lt;code&gt;src/pages/&lt;/code&gt;. Inside that folder, create &lt;code&gt;[id].astro&lt;/code&gt;. This generates dynamic paths for every article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import Layout from "@/layouts/Layout.astro";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import NDK, { type NDKEvent } from "@nostr-dev-kit/ndk";
import 'ws';
import { parseNostrMarkdown } from "@/utils/parseMarkdown";
import { formatNostrEvent } from "@/utils/formatNostrEvent";

export async function getStaticPaths() {
  const ndk = new NDK({ explicitRelayUrls: ["wss://relay.damus.io", "wss://nos.lol"] });
  await ndk.connect(3000);

  let events: Set&amp;lt;NDKEvent&amp;gt; = new Set();

  // REMEMBER TO INSERT YOUR HEX KEY BELOW
  const filter = { kinds: [30023], authors: ["YOUR_HEX_PUBLIC_KEY_HERE"] };
  const fetchPromise = ndk.fetchEvents(filter, { closeOnEose: true });
  const timeoutPromise = new Promise&amp;lt;Set&amp;lt;NDKEvent&amp;gt;&amp;gt;((resolve) =&amp;gt; setTimeout(() =&amp;gt; resolve(new Set()), 4000));

  events = await Promise.race([fetchPromise, timeoutPromise]);

  return Array.from(events)
    .filter((e): e is NDKEvent &amp;amp; { created_at: number } =&amp;gt; e.created_at !== undefined)
    .map(e =&amp;gt; ({
      params: { id: e.id },
      props: { event: e }
    }));
}

interface Props { event: NDKEvent; }
const { event } = Astro.props;
const post = formatNostrEvent(event);
const htmlContent = await parseNostrMarkdown(post.content);
---

&amp;lt;Layout title={post.title}&amp;gt;
  &amp;lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" crossorigin="anonymous" /&amp;gt;
  &amp;lt;Header /&amp;gt;

  &amp;lt;main id="main-content" class="mx-auto w-full max-w-3xl px-4 pb-12 mt-8"&amp;gt;
    &amp;lt;button class="focus-outline mb-6 flex hover:opacity-75" onclick="history.back()"&amp;gt;
      &amp;lt;span&amp;gt;← Go back&amp;lt;/span&amp;gt;
    &amp;lt;/button&amp;gt;
    &amp;lt;h1 class="text-3xl font-bold text-skin-accent"&amp;gt;{post.title}&amp;lt;/h1&amp;gt;

    {post.naddr &amp;amp;&amp;amp; (
      &amp;lt;div class="mt-6 flex flex-wrap items-center gap-3 text-sm bg-skin-card/10 p-4 rounded-lg border border-skin-line/50"&amp;gt;
        &amp;lt;span class="font-bold"&amp;gt;⚡ Nostr:&amp;lt;/span&amp;gt;
        &amp;lt;a href={`nostr:${post.naddr}`} class="text-skin-accent hover:underline"&amp;gt;Open in App&amp;lt;/a&amp;gt;
        &amp;lt;a href={`https://yakihonne.com/article/${post.naddr}`} target="_blank" class="hover:text-skin-accent opacity-80"&amp;gt;Yakihonne&amp;lt;/a&amp;gt;
      &amp;lt;/div&amp;gt;
    )}

    &amp;lt;article class="prose max-w-none prose-img:border-0 mt-8" set:html={htmlContent} /&amp;gt;
  &amp;lt;/main&amp;gt;
  &amp;lt;Footer /&amp;gt;
&amp;lt;/Layout&amp;gt;

&amp;lt;script&amp;gt;
  const renderMermaid = async () =&amp;gt; {
    const codeBlocks = document.querySelectorAll("pre code.language-mermaid");
    if (codeBlocks.length === 0) return;
    const { default: mermaid } = await import("https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs");
    mermaid.initialize({ startOnLoad: false, theme: "dark" });

    for (const element of codeBlocks) {
      const id = `mermaid-${Math.random().toString(36).substr(2, 9)}`;
      const { svg } = await mermaid.render(id, element.textContent || "");
      const wrapper = document.createElement('div');
      wrapper.className = 'mermaid-container my-8 flex justify-center overflow-x-auto';
      wrapper.innerHTML = svg;
      element.parentElement?.replaceWith(wrapper);
    }
  };
  renderMermaid();
  document.addEventListener("astro:after-swap", renderMermaid);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Global Styling and Contrast Fixes
&lt;/h3&gt;

&lt;p&gt;Add these definitions to &lt;code&gt;src/styles/global.css&lt;/code&gt; to fix dark mode contrast, ensure math blocks scroll gracefully on mobile, and apply proper borders to user-uploaded images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Improve contrast for Dark Mode */&lt;/span&gt;
&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"dark"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.prose&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--tw-prose-body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"colors.slate.200"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--tw-prose-headings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"colors.white"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--tw-prose-bold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"colors.white"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* KaTeX Math Styling */&lt;/span&gt;
&lt;span class="nc"&gt;.katex-display&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;my-8&lt;/span&gt; &lt;span class="err"&gt;overflow-x-auto&lt;/span&gt; &lt;span class="err"&gt;py-4&lt;/span&gt; &lt;span class="err"&gt;px-2&lt;/span&gt; &lt;span class="err"&gt;rounded-lg;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.03&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.katex&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Nostr Image Attachments */&lt;/span&gt;
&lt;span class="nt"&gt;article&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;rounded-xl&lt;/span&gt; &lt;span class="err"&gt;border&lt;/span&gt; &lt;span class="err"&gt;shadow-md&lt;/span&gt; &lt;span class="err"&gt;mx-auto&lt;/span&gt; &lt;span class="err"&gt;my-8;&lt;/span&gt;
  &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-line&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;Start your local server by running &lt;code&gt;npm run dev&lt;/code&gt; and opening &lt;code&gt;http://localhost:4321&lt;/code&gt;. Your site should now dynamically render your Nostr notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 4: AI-Native SEO (&lt;code&gt;llm.txt&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;As AI agents like Perplexity and SearchGPT replace traditional search engines, we must provide a semantic layer.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;llm.txt&lt;/code&gt; inside your &lt;code&gt;public/&lt;/code&gt; folder. Write a direct, markdown-formatted summary of your site's core philosophy and architecture. When an AI scrapes &lt;code&gt;yourwebsite.com/llm.txt&lt;/code&gt;, it immediately contextualizes your niche with zero token waste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 5: Deployment &amp;amp; The Zero-Maintenance Pipeline
&lt;/h2&gt;

&lt;p&gt;It is time to put your site on the public internet and automate the build process.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push your code to a new public GitHub repository.&lt;/li&gt;
&lt;li&gt;Log into Vercel, click &lt;strong&gt;Add New Project&lt;/strong&gt;, import your repository, and click &lt;strong&gt;Deploy&lt;/strong&gt;. Vercel will grant you a live URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Automation Webhook
&lt;/h3&gt;

&lt;p&gt;Right now, your site is static. If you publish a new article on Nostr, your site won't update until Vercel builds again.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In your Vercel Dashboard, navigate to &lt;strong&gt;Settings -&amp;gt; Git -&amp;gt; Deploy Hooks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create a hook named &lt;code&gt;Nostr-Sync&lt;/code&gt; on the &lt;code&gt;main&lt;/code&gt; branch and copy the generated URL.&lt;/li&gt;
&lt;li&gt;In your GitHub repository, go to the &lt;strong&gt;Actions&lt;/strong&gt; tab and create a new workflow named &lt;code&gt;nostr-sync.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Paste the following configuration, replacing the URL with your unique Vercel hook:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Nostr Auto-Sync&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*/6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Trigger Vercel Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -X POST "https://api.vercel.com/v1/integrations/deploy/YOUR_UNIQUE_VERCEL_HOOK_URL"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit the changes.&lt;/p&gt;

&lt;p&gt;You have successfully engineered an evergreen architecture. You write natively on Nostr, retaining absolute ownership of your cryptographic keys. Every 6 hours, GitHub Actions silently signals Vercel. Vercel scrapes the relays, compiles your latest thoughts into high-speed HTML, and serves it globally. Write once, syndicate everywhere.&lt;/p&gt;

</description>
      <category>nostr</category>
      <category>kheai</category>
      <category>astro</category>
      <category>seo</category>
    </item>
    <item>
      <title>Zeroing Out the Bill: The Developer’s Practical Guide to Eliminating Google Cloud (GCP) Idle Costs</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Tue, 02 Jun 2026 07:20:06 +0000</pubDate>
      <link>https://dev.to/kheai/zeroing-out-the-bill-the-developers-practical-guide-to-eliminating-google-cloud-gcp-idle-costs-34c3</link>
      <guid>https://dev.to/kheai/zeroing-out-the-bill-the-developers-practical-guide-to-eliminating-google-cloud-gcp-idle-costs-34c3</guid>
      <description>&lt;p&gt;It is a classic developer milestone: you finish a side project, proof-of-concept, or staging test, and you responsibly tear down your infrastructure. You scale your compute instances to zero, delete or pause your databases, and walk away believing your cloud spend has dropped to absolute zero.&lt;/p&gt;

&lt;p&gt;Then, the billing dashboard updates. You spot a persistent trickle of costs—fractions of a cent tracking a linear line upwards across your billing period. While the numbers seem trivial at a small scale (fractions of a cent tracking toward a dollar), these phantom charges represent a fundamental design mechanic in cloud systems: &lt;strong&gt;the hidden tax of at-rest storage&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Core Rule of Cloud Billing:&lt;/strong&gt; Compute is easily turned off, but data has gravity. If it occupies physical sectors on a disk in a cloud data center somewhere, Google will bill you for it—even if your applications are completely dark.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This guide details exactly why these costs happen, builds a framework for all potential dormant cloud costs you must guard against, and outlines automated strategies to achieve a true $0.00 infrastructure bill when your code is idle.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Anatomy of the Staging Bill
&lt;/h2&gt;

&lt;p&gt;When analyzing a low-cost, idle cloud project dashboard, expenditures typically pool into three specific storage-based categories after compute instances are scaled down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Artifact Registry:&lt;/strong&gt; Charges arise from hosting historical application build containers, package fragments, or deployment source artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud SQL (Metadata/Storage Component):&lt;/strong&gt; Even if an instance is stopped or deleted, persistent disks, backups, and IP assignments can sustain unyielding baseline costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Storage (GCS):&lt;/strong&gt; Acts as the underlying system storage bucket infrastructure where automated frameworks drop deployment bundles, pipeline states, and continuous integration caches.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Deep-Dive: Remediation &amp;amp; Automation Strategies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Artifact Registry: Purging Container Bloat
&lt;/h3&gt;

&lt;p&gt;Every single time a deployment pipeline runs (e.g., deploying code to Cloud Run), a baseline container image is generated and stored inside the Artifact Registry repository. Over weeks of iterations, these untagged historical layers build up significant digital debris.&lt;/p&gt;

&lt;h4&gt;
  
  
  🛠️ The Permanent Automated Fix
&lt;/h4&gt;

&lt;p&gt;Do not rely on manual cleanup. Set up a declarative &lt;strong&gt;Cleanup Policy&lt;/strong&gt; inside your repository:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Artifact Registry &amp;gt; Repositories&lt;/strong&gt; and select your deployment repository.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Edit Repository&lt;/strong&gt; and scroll down to the &lt;strong&gt;Cleanup policies&lt;/strong&gt; manager.&lt;/li&gt;
&lt;li&gt;Add a rule with the condition &lt;strong&gt;Tag State: Any Tag State&lt;/strong&gt; combined with an age threshold like &lt;code&gt;Older than: 7d&lt;/code&gt; (7 days).&lt;/li&gt;
&lt;li&gt;Change the evaluation enforcement action from &lt;em&gt;Dry Run&lt;/em&gt; to &lt;strong&gt;Delete artifacts&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cloud Storage: Mitigating Automated Backend Artifacts
&lt;/h3&gt;

&lt;p&gt;Tools like Cloud Build naturally create cloud storage buckets (e.g., &lt;code&gt;staging.project-id.appspot.com&lt;/code&gt; or &lt;code&gt;project-id_cloudbuild&lt;/code&gt;) to compress and transport your code source before compiling it. These source zip files often remain forever unless lifecycle management intervenes.&lt;/p&gt;

&lt;p&gt;To eliminate these costs passively, implement Object Lifecycle Management rules on your buckets via the console or globally via the &lt;code&gt;gcloud&lt;/code&gt; CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{"rule": [{"action": {"type": "Delete"}, "condition": {"age": 7}}]}'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; lifecycle.json
gcloud storage buckets update gs://YOUR_BUILDS_BUCKET &lt;span class="nt"&gt;--lifecycle-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lifecycle.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ &lt;strong&gt;Watch Out for the "Soft Delete" Catch:&lt;/strong&gt; Google Cloud includes a default &lt;strong&gt;Soft Delete Policy&lt;/strong&gt; on all new buckets. When an object lifecycle rule executes, or you manually delete a file, the object is placed in an invisible soft-deleted state for &lt;strong&gt;7 days&lt;/strong&gt; to allow recovery. During this window, you are still billed at regular storage rates! To achieve immediate bill reduction, click the bucket's &lt;strong&gt;Configuration&lt;/strong&gt; tab, locate the Soft Delete Policy, edit it, and set the duration value to &lt;code&gt;0 days&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Comprehensive Checklist: Every Potential Idle Cost in GCP
&lt;/h2&gt;

&lt;p&gt;To ensure your environment does not accumulate unexpected bills, use this definitive reference table outlining common services, their hidden idle costs, and exact mitigation vectors:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Service Category&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;What Charges You While Idle&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Estimated Unit Cost (US)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Mitigation Action&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud Run / GCF&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Minimum CPU Instances allocated to stay warm; CPU allocation set to "Always Allocated".&lt;/td&gt;
&lt;td&gt;~0.04 / vCPU-hour&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;min-instances&lt;/code&gt; to 0; switch CPU allocation to "Only during request processing".&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Artifact Registry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Active container storage layer data at-rest.&lt;/td&gt;
&lt;td&gt;~0.10 per GB / month&lt;/td&gt;
&lt;td&gt;Apply automated Repository Cleanup Policies (Age &amp;lt; 7-14 days).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standard, Nearline, or Coldline storage data; Soft-deleted objects waiting out retention windows.&lt;/td&gt;
&lt;td&gt;~0.02 to 0.026 per GB / month (Standard)&lt;/td&gt;
&lt;td&gt;Set Object Lifecycle policies to auto-delete; modify Soft Delete retention to 0 days.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud SQL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Persistent Disk space (SSD/HDD); Automated database backup snapshots; Retained Static IP configurations.&lt;/td&gt;
&lt;td&gt;~0.17 per GB/mo (SSD) ~0.01 to 0.025 per hour for IP&lt;/td&gt;
&lt;td&gt;Stopping instances halts CPU/RAM charges but &lt;strong&gt;keeps charging for disk/IPs&lt;/strong&gt;. Clone data, export to GCS, and delete the instance fully.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compute Engine&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unattached Persistent Disks (PDs); Orphaned Static External IP Addresses.&lt;/td&gt;
&lt;td&gt;~0.04 per GB/mo (Standard) ~0.01 / hour idle IP&lt;/td&gt;
&lt;td&gt;Go to Compute Engine &amp;gt; Disks and delete detached storage; Release unused static external IPs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VPC Networking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Forwarding rules (Load Balancers left running without active backends); NAT Gateways.&lt;/td&gt;
&lt;td&gt;~0.025+ per hour per rule / gateway&lt;/td&gt;
&lt;td&gt;Delete idle External HTTP(S) Load Balancers and Cloud NAT gateways when unneeded.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vertex AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dormant custom notebooks (User-managed instances); Deployed endpoints hosting models.&lt;/td&gt;
&lt;td&gt;Varies by underlying Compute Engine sizing&lt;/td&gt;
&lt;td&gt;Stop Vertex Workbench notebooks when not coding; Undeploy models from active prediction endpoints.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Logging &amp;amp; Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Log ingestion exceeding the free 50 GiB/month limit; Custom metric collection data.&lt;/td&gt;
&lt;td&gt;~0.50 per GiB ingested&lt;/td&gt;
&lt;td&gt;Set up log exclusion filters to drop high-volume stdout/stderr debug records.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Summary Blueprint for Staging Environments
&lt;/h2&gt;

&lt;p&gt;To keep your non-production workloads under absolute financial control, embed the following hygiene habits into your architectural processes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as Code (IaC):&lt;/strong&gt; Define environment testbeds completely in Terraform. Instead of spinning services down or pausing individual configurations, execute a wholesale &lt;code&gt;terraform destroy&lt;/code&gt; when the sprint or research spike ends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budget Alerts with Pub/Sub:&lt;/strong&gt; Do not rely on looking at the console. Create a hyper-sensitive budget alert (e.g., at $1.00) linked to a Cloud Function that automatically initiates teardowns if thresholds are breached.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tagging and Labels:&lt;/strong&gt; Label everything with &lt;code&gt;env: staging&lt;/code&gt; or &lt;code&gt;owner: developer_name&lt;/code&gt;. This lets you sort your billing console instantly by labels to identify which resource group is generating background noise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By shifting from manual infrastructure adjustments to structured automated lifecycles, you turn cloud cost optimization into an immutable background process—leaving your dashboard clean, predictable, and flat.&lt;/p&gt;

</description>
      <category>gcp</category>
      <category>kheai</category>
      <category>infrastructure</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Barbell Founder: Why I Chose to be a Part-timer to Protect My Startup</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Sun, 10 May 2026 14:50:07 +0000</pubDate>
      <link>https://dev.to/kheai/the-barbell-founder-why-i-chose-to-be-a-part-timer-to-protect-my-startup-31pb</link>
      <guid>https://dev.to/kheai/the-barbell-founder-why-i-chose-to-be-a-part-timer-to-protect-my-startup-31pb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Stop optimizing for nominal wages. Start optimizing for cognitive surplus and time sovereignty.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the modern startup ecosystem, there is a piece of conventional wisdom that acts as a silent killer: &lt;em&gt;“Get a high-paying, stable corporate job to fund your dream.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On paper, it sounds responsible. In reality, it is a trap. For a founder—especially a technical one—a high-status full-time role is often a "gold-plated cage" that drains your energy, steals your intellectual property, and ensures you never have the "escape velocity" needed to launch.&lt;/p&gt;

&lt;p&gt;I have abandoned that path. Instead, I have adopted a radical decoupling of &lt;strong&gt;Survival&lt;/strong&gt; from &lt;strong&gt;Self-Actualization&lt;/strong&gt;. I call it the &lt;strong&gt;Low-Entropy Employment Model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/protocol/260510-barbell-founder_p14yTs7I4.png" 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.amazonaws.com%2Fuploads%2Farticles%2F1org8rvfvvyi2kaabq3f.png" alt="The Barbell Founder: Why I Chose an RM 8.72 Walking Job to Protect My Startup" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Strategy: Nassim Taleb’s Barbell
&lt;/h2&gt;

&lt;p&gt;In finance, the Barbell Strategy involves avoiding the "middle ground." You place 90% of your resources in hyper-safe, boring assets to guarantee survival, and 10% in highly aggressive, speculative bets for massive upside.&lt;/p&gt;

&lt;p&gt;I have applied this to my life:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Safety (90%):&lt;/strong&gt; A "mindless," part-time, or contract job that is walkable and stress-free. It provides the &lt;strong&gt;Minimum Viable Income&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Aggression (10%):&lt;/strong&gt; My startup. This is where 100% of my ambition, creativity, and aggression are focused.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most people get stuck in the middle—a moderately stressful, moderately paying job that pays just enough to stay comfortable, but drains just enough energy to stay stagnant.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Biology: Cognitive Surplus vs. Ego Depletion
&lt;/h2&gt;

&lt;p&gt;Why do I prioritize "mindless" work? Because of a psychological reality called &lt;strong&gt;Ego Depletion&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The human brain has a finite daily reservoir of willpower and decision-making capacity. If your day job requires you to solve complex algorithmic problems, navigate toxic office politics, or manage high-stakes client crises, your prefrontal cortex is chemically exhausted by 5:00 PM.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Founder’s Axiom:&lt;/strong&gt; Free time is useless if you have no cognitive energy left to spend.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By choosing a low-entropy job, I arrive at my "startup hours" with my nervous system intact. I am not "recovering" from my day job; I am starting my real day with a full battery.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Math: The "True Hourly Rate" Illusion
&lt;/h2&gt;

&lt;p&gt;Let’s use a skeptical, research-based simulation to debunk the "higher pay" myth. Consider two options for a 5-hour part-time shift (20 days/month):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Option A:&lt;/strong&gt; A local job within walking distance. Pay: &lt;strong&gt;RM 8.72/hr&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option B:&lt;/strong&gt; A "better" job requiring a commute (MRT/LRT). Pay: &lt;strong&gt;RM 11.00/hr&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Society says take Option B. The math says otherwise when we calculate the &lt;strong&gt;Total Cost of Employment (TCE)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;$$True\ Hourly\ Rate = \frac{Total\ Daily\ Income}{Hours\ Worked + Commute\ Time}$$&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Metric&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Option A (Local)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Option B (Commute)&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gross Daily Income&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RM 43.60&lt;/td&gt;
&lt;td&gt;RM 55.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Time Invested&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.5 Hours (0.5h walk)&lt;/td&gt;
&lt;td&gt;7.5 Hours (2.5h transit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;True Hourly Rate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;RM 7.92 / hr&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;RM 7.33 / hr&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The Verdict:&lt;/strong&gt; Option B is a net loss. Not only is the true rate lower, but the &lt;strong&gt;Opportunity Cost&lt;/strong&gt; is 40 hours of lost time per month. Those 40 hours could be used to write 3 government grants, pitch 50 investors, or build a core product feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Invisible Chains: The Risk of Full-Time
&lt;/h2&gt;

&lt;p&gt;For a programmer or technical founder, a salaried full-time role is strategically dangerous.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Intellectual Property (IP) Trap
&lt;/h3&gt;

&lt;p&gt;Standard full-time contracts often include "Assignment of Inventions" clauses. Legally, any code you write—even on your own laptop at 2:00 AM—can be claimed by your employer if it’s even tangentially related to their field.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Freelance or part-time contracts are "cleaner." They define a narrow scope of work, leaving your "after-hours" IP safely in your hands.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Identity Tax"
&lt;/h3&gt;

&lt;p&gt;Corporate culture demands emotional "alignment." They want you to care about &lt;em&gt;their&lt;/em&gt; vision. This creates an &lt;strong&gt;Emotional Sunk Cost&lt;/strong&gt;. You start optimizing for a promotion you don't actually want, which tethers your self-worth to a hierarchy you don't own.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Non-Compete Chokehold
&lt;/h3&gt;

&lt;p&gt;Full-time roles often come with non-compete clauses that can legally block you from launching a startup in a similar industry for years. mercenary, part-time roles rarely carry this legal weight.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The Execution
&lt;/h2&gt;

&lt;p&gt;This strategy is not a "slack-off" plan. It is an &lt;strong&gt;optimization plan&lt;/strong&gt;. To make it work, you must adhere to three strict rules:&lt;/p&gt;

&lt;h3&gt;
  
  
  I. Minimalist Consumption
&lt;/h3&gt;

&lt;p&gt;You cannot live a high-status lifestyle on a low-entropy income. You must be a &lt;strong&gt;Minimalist in Consumption&lt;/strong&gt; to remain a &lt;strong&gt;Maximalist in Production&lt;/strong&gt;. Every RM saved is a second of freedom bought.&lt;/p&gt;

&lt;h3&gt;
  
  
  II. The Health &amp;amp; Legal Buffer
&lt;/h3&gt;

&lt;p&gt;Since you are forgoing corporate benefits, you must be disciplined:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Insurance:&lt;/strong&gt; Use a portion of your income to secure your own medical and life insurance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contract Review:&lt;/strong&gt; Never sign a part-time contract without checking for IP-grabbing clauses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  III. The Discipline Filter
&lt;/h3&gt;

&lt;p&gt;If you take an "easy" job but spend your reclaimed 40 hours on Netflix or gaming, you aren't a Barbell Founder—you are just underemployed. This strategy only works if you go to "war" for your startup the moment you clock out of your survival job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Time Sovereignty is the Ultimate Weapon
&lt;/h2&gt;

&lt;p&gt;In the startup game, the person who can stay in the arena the longest wins. By lowering your burn rate and protecting your cognitive energy, you become incredibly difficult to kill.&lt;/p&gt;

&lt;p&gt;Stop optimizing for a job title. Start optimizing for &lt;strong&gt;Time Sovereignty&lt;/strong&gt;. Your startup deserves your best brain—don't sell it to the highest bidder for a few extra Ringgit and a long commute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is your "True Hourly Rate" today? Is it time to quit the "good" job for the right one?&lt;/strong&gt; &lt;/p&gt;

</description>
      <category>startup</category>
      <category>career</category>
      <category>kheai</category>
      <category>programmers</category>
    </item>
    <item>
      <title>Building an AI-Powered ERP System with Gemma 26B MoE, .NET 8, Python &amp; React</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Sat, 09 May 2026 06:25:26 +0000</pubDate>
      <link>https://dev.to/kheai/building-an-ai-powered-erp-system-with-gemma-26b-moe-net-8-python-react-3noh</link>
      <guid>https://dev.to/kheai/building-an-ai-powered-erp-system-with-gemma-26b-moe-net-8-python-react-3noh</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Write About Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Building an industrial-grade SaaS from scratch can feel daunting. As a software engineer, I’ve found that the secret to not getting overwhelmed is architecture. When you break down complex monolithic systems into manageable, robust microservices, that’s where the real fun begins.&lt;/p&gt;

&lt;p&gt;Recently, I built &lt;strong&gt;Y&amp;amp;Y App (yny)&lt;/strong&gt;—a comprehensive, microservices-based ERP-lite system. But it doesn't just manage inventory; it integrates a specialized AI Domain-Expert Agent that can read technical manuals and troubleshoot industrial equipment in real-time.&lt;/p&gt;

&lt;p&gt;In this masterclass, I am going to walk you through exactly how I built it, step-by-step. By the end of this guide, you will transition from a blank folder to a fully functioning, production-ready SaaS prototype deployed to the cloud.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Deliverables
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/kheAI/yny-app" rel="noopener noreferrer"&gt;kheAI/yny-app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Video Demo:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=FsEYWDAcwsw" rel="noopener noreferrer"&gt;Watch on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Vercel Live Demo&lt;/strong&gt;: &lt;a href="https://yny-ui.vercel.app/" rel="noopener noreferrer"&gt;Play&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/FsEYWDAcwsw"&gt;
  &lt;/iframe&gt;
 &lt;/p&gt;
&lt;h2&gt;
  
  
  🏗️ The Architecture &amp;amp; Tech Stack (The "Why")
&lt;/h2&gt;

&lt;p&gt;To ensure data integrity, prevent our apps from becoming logically entangled, and allow independent scaling, I chose a strict &lt;strong&gt;Microservices Architecture&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Here is what we are using and why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Data Tier:&lt;/strong&gt; Google Cloud SQL (PostgreSQL). We are using the &lt;code&gt;pgvector&lt;/code&gt; extension so our database can handle &lt;em&gt;both&lt;/em&gt; standard relational data (inventory) and mathematical arrays (AI memory/embeddings) in the same place.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Logic Tier (ERP):&lt;/strong&gt; A type-safe &lt;strong&gt;.NET 8 Web API&lt;/strong&gt;. C# is the industry standard for fast, secure delivery of structured business data.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Logic Tier (AI):&lt;/strong&gt; A &lt;strong&gt;Python FastAPI&lt;/strong&gt; service. Python is the undisputed king of AI. This service executes a &lt;a href="https://ai.google.dev/gemini-api/docs/embeddings" rel="noopener noreferrer"&gt;Retrieval-Augmented Generation (RAG)&lt;/a&gt; workflow using the &lt;strong&gt;Gemini API&lt;/strong&gt; (refer Github Repo for Vertex AI version too).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Presentation Tier:&lt;/strong&gt; A responsive frontend built with &lt;strong&gt;React and Vite&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hosting:&lt;/strong&gt; Serverless, auto-scaling backend deployments via &lt;strong&gt;Google Cloud Run&lt;/strong&gt; (meaning you only pay when people use it), with the frontend hosted on &lt;strong&gt;Vercel&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Engineer's Note on AI Models:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For this tutorial, we are utilizing the Gemini API. &lt;/li&gt;
&lt;li&gt;We'll use the &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; for interactive apps or agents where &lt;strong&gt;low latency&lt;/strong&gt; is important. A 26B Mixture-of-Experts (MoE) model that offers fast inference by using only ~4B active parameters. It offers nearly the same intelligence as the 31B model but runs significantly faster because it only activates a fraction of its parameters (4B) per token. &lt;/li&gt;
&lt;li&gt;For Embeddings, we choose &lt;code&gt;gemini-embedding-001&lt;/code&gt; to turn our text into 768-dimensional mathematical vectors. For multimodal model, can try &lt;code&gt;gemini-embedding-2&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;The Gemini API SDK's default to &lt;code&gt;v1beta&lt;/code&gt;, but you can opt to use other versions by setting the API version &lt;code&gt;genai.Client(http_options={'api_version': 'v1'})&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260509-yny-gemini-api-rate-limit_nqq-NibK1.png" 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.amazonaws.com%2Fuploads%2Farticles%2F3bihtggga9soibxpb0u3.png" alt="yny-gemini-api-rate-limit" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  How the System Flows
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260509-yny-workflow_bFOldGiR_.png" 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.amazonaws.com%2Fuploads%2Farticles%2Ffo2h4yhz5n993t3c4yym.png" alt="yny-workflow" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🛠️ Phase 0: Workspace Setup &amp;amp; Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before writing a single line of code, we need to set up our workbench. &lt;/p&gt;
&lt;h3&gt;
  
  
  1. The Tools You Need
&lt;/h3&gt;

&lt;p&gt;Ensure you have the following installed on your machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Google Cloud Account:&lt;/strong&gt; Create a project (e.g., &lt;code&gt;yny-saas-2024&lt;/code&gt;). Write down your &lt;strong&gt;Project ID&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;gcloud CLI:&lt;/strong&gt; Installed and authenticated. Run &lt;code&gt;gcloud auth login&lt;/code&gt;, then &lt;code&gt;gcloud config set project YOUR_PROJECT_ID&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;.NET 8 SDK:&lt;/strong&gt; For our C# backend. Verify with &lt;code&gt;dotnet --version&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Python 3.10+:&lt;/strong&gt; For the AI service. Verify with &lt;code&gt;python3 --version&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Node.js (LTS):&lt;/strong&gt; For the React frontend. Verify with &lt;code&gt;node -v&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Gemini API Key:&lt;/strong&gt; Get one for free from &lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. The Directory Structure
&lt;/h3&gt;

&lt;p&gt;Create a master folder. This will act as the "monorepo" for our three microservices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;yny-app
&lt;span class="nb"&gt;cd &lt;/span&gt;yny-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260508-yny-app-structure_RF3iFMSJj.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fx3lclkv4vokd32md4nia.png" alt="yny-app-structure" width="598" height="1844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crucial Step:&lt;/strong&gt; Create a &lt;code&gt;.gitignore&lt;/code&gt; file in this root folder immediately. This prevents you from accidentally uploading database passwords or API keys to GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yny-app/.gitignore
node_modules/
bin/
obj/
venv/
.env
appsettings.json
.DS_Store
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🗄️ Phase 1: The Cloud Database (Postgres + pgvector)
&lt;/h2&gt;

&lt;p&gt;We need a database capable of standard SQL (for products) and Vector Math (for the AI). &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Provision the Database
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;strong&gt;Google Cloud Console&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Cloud SQL&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Create Instance&lt;/strong&gt; -&amp;gt; &lt;strong&gt;PostgreSQL&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instance ID:&lt;/strong&gt; &lt;code&gt;yny-db-instance&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password:&lt;/strong&gt; &lt;code&gt;YnySecurePass26&lt;/code&gt; &lt;em&gt;(Write this down! Avoid characters like &lt;code&gt;@&lt;/code&gt; or &lt;code&gt;#&lt;/code&gt; to prevent URL parsing errors).&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edition:&lt;/strong&gt; Choose &lt;strong&gt;Enterprise&lt;/strong&gt; (Sandbox/Shared Core) to keep costs near zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Region:&lt;/strong&gt; &lt;code&gt;us-central1&lt;/code&gt;. Click &lt;strong&gt;Create&lt;/strong&gt; (Takes ~5 minutes).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Seed the Schema &amp;amp; Data
&lt;/h3&gt;

&lt;p&gt;Once running, open the &lt;strong&gt;Google Cloud Shell&lt;/strong&gt; (the terminal icon at the top right of the GCP console) and connect to your database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud sql connect yny-db-instance &lt;span class="nt"&gt;--user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted, paste your password. Then, run this SQL script to build your foundation:&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;-- 1. Enable pgvector for AI Memory&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;EXTENSION&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- 2. Create the ERP Tables&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ProductCode&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ProductName&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Category&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;QuantityInStock&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&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;Status&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'Active'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- 3. Create the AI Knowledge Base Table&lt;/span&gt;
&lt;span class="c1"&gt;-- Google's embeddings model outputs exactly 768 dimensions&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;manual_knowledge&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;product_code&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ProductCode&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;section_title&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;text_chunk&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="n"&gt;VECTOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- 4. Insert Production-Alike ERP Data&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;Products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ProductCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProductName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QuantityInStock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Status&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="s1"&gt;'PUMP-CENT-001'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Centrifugal Pump - Model X1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Pumps'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Active'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SENS-VIB-99'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Vibration Sensor - Wireless'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sensors'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Active'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'VALVE-GATE-05'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Heavy Duty Gate Valve'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Valves'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Out of Stock'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- 5. Check&lt;/span&gt;
&lt;span class="c1"&gt;-- Check Your ERP Inventory (Basic)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Filter for Critical Items (Low/No Stock)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;ProductCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProductName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QuantityInStock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;QuantityInStock&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Out of Stock'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Safely Check the AI Knowledge Base&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;product_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;section_title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_chunk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;manual_snippet&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;manual_knowledge&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Verify the AI Vector Dimensions&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;product_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;vector_dims&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;vector_dimensions&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;manual_knowledge&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- The "Big Picture" JOIN Query&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QuantityInStock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;section_title&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;AI_Manual_Available&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;manual_knowledge&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product_code&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;\q&lt;/code&gt; and press Enter to exit. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Take Note:&lt;/strong&gt; Go to your Cloud SQL dashboard and copy the &lt;strong&gt;Public IP&lt;/strong&gt; of your database. You will need it for the next steps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260508-yny-postgres-insert_Un7udGH60o.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fi2omwsttw1c9437fan4m.png" alt="yny-postgres-insert" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260508-yny-postgres-queries_Hzubij3WJV.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fpffqr3ypm4xpxoxspqfn.png" alt="yny-postgres-queriesg" width="800" height="1180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Phase 2: The ERP Backend (.NET 8 Web API)
&lt;/h2&gt;

&lt;p&gt;C# is my go-to for enterprise logic. It is blazingly fast and highly structured. We will build a lightweight API to serve our inventory data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Initialize the Project
&lt;/h3&gt;

&lt;p&gt;In your local terminal (inside the &lt;code&gt;yny-app&lt;/code&gt; folder):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new webapi &lt;span class="nt"&gt;-n&lt;/span&gt; yny.Api
&lt;span class="nb"&gt;cd &lt;/span&gt;yny.Api
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Database Connection String
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;yny.Api/appsettings.json&lt;/code&gt;. Configure your connection string replacing &lt;code&gt;YOUR_DB_IP&lt;/code&gt; with your database's Public IP:&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;"Logging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"LogLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Information"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Microsoft.AspNetCore"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Warning"&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;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AllowedHosts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ConnectionStrings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"DefaultConnection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Host=YOUR_DB_IP;Database=postgres;Username=postgres;Password=YnySecurePass26"&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;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;h3&gt;
  
  
  Step 3: Write the API Logic
&lt;/h3&gt;

&lt;p&gt;We are using &lt;strong&gt;Minimal APIs&lt;/strong&gt; to keep our code clean. Open &lt;code&gt;Program.cs&lt;/code&gt; and replace &lt;em&gt;everything&lt;/em&gt; with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.EntityFrameworkCore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.ComponentModel.DataAnnotations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.ComponentModel.DataAnnotations.Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&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;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AllowAll"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithOrigins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"http://localhost:5173"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"http://localhost:3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"https://yny-ui.vercel.app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"https://yny-ui-158766252751.us-central1.run.app"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyHeader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllowAnyMethod&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetConnectionString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DefaultConnection"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseNpgsql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connString&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;//.UseLowerCaseNamingConvention());&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseCors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AllowAll"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&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;=&amp;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;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ERP API running"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/products"&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="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&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="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/products/{code}"&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FindAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&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;product&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;app&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="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"products"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"productcode"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ProductCode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"productname"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ProductName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quantityinstock"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;QuantityInStock&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="nf"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppDbContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DbContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DbContextOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&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="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DbSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Test it:&lt;/em&gt; Run &lt;code&gt;dotnet run&lt;/code&gt;. Open your browser to &lt;code&gt;http://localhost:5000/api/products&lt;/code&gt; to see your JSON data!&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Phase 3: The AI Microservice (Python + FastAPI)
&lt;/h2&gt;

&lt;p&gt;This is the "Brain" of our application. We are using a pattern called &lt;strong&gt;RAG (Retrieval-Augmented Generation)&lt;/strong&gt;. When a user asks a question, this service turns the question into math, finds similar mathematical concepts in our Postgres database, and feeds that exact manual to the LLM to get a factual answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Python Setup
&lt;/h3&gt;

&lt;p&gt;Open a new terminal tab. Go back to your &lt;code&gt;yny-app&lt;/code&gt; root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;yny.AI
&lt;span class="nb"&gt;cd &lt;/span&gt;yny.AI
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate  &lt;span class="c"&gt;# On Windows use: venv\Scripts\activate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;requirements.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastapi
uvicorn
psycopg2-binary
python-dotenv
google-generativeai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run: &lt;code&gt;pip install -r requirements.txt&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configure Secrets
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in the &lt;code&gt;yny.AI&lt;/code&gt; folder (replace &lt;code&gt;YOUR_DB_IP&lt;/code&gt; and &lt;code&gt;YOUR_API_KEY&lt;/code&gt;):&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;DB_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql://postgres:YnySecurePass26@YOUR_DB_IP:5432/postgres
&lt;span class="nv"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_API_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Write the RAG Pipeline (&lt;code&gt;main.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;main.py&lt;/code&gt;. Notice the SQL query using &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt;. This is the &lt;code&gt;pgvector&lt;/code&gt; operator for &lt;em&gt;Cosine Distance&lt;/em&gt;—it calculates how closely related the user's question is to our manuals!&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi.middleware.cors&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CORSMiddleware&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;google.generativeai&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;psycopg2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CORSMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allow_origins&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;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;allow_methods&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;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;allow_headers&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;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize Gemini
&lt;/span&gt;&lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&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="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GenerativeModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemma-4-26b-a4b-it&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;)

@app.get(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)
def root():
    return {&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="n"&gt;AI&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt; &lt;span class="n"&gt;perfectly&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;}

@app.get(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;troubleshoot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)
async def troubleshoot(question: str, product_code: str):
    try:
        # Step 1: Convert question to vector
        embedding_result = genai.embed_content(
            model=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="n"&gt;gemini&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;001&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,
            content=question,
            output_dimensionality=768
        )
        query_vector = embedding_result[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;embedding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]

        # Step 2: Search Postgres using pgvector Cosine Distance (&amp;lt;=&amp;gt;)
        conn = psycopg2.connect(os.getenv(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="n"&gt;DB_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;))
        cur = conn.cursor()
        query = &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            SELECT text_chunk FROM manual_knowledge 
            WHERE product_code = %s 
            ORDER BY embedding &amp;lt;=&amp;gt; %s::vector LIMIT 1
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        cur.execute(query, (product_code, query_vector))
        result = cur.fetchone()
        conn.close()

        context = result[0] if result else &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;manual&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;

        # Step 3: Generate answer with Gemma
        prompt = f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        You are an expert industrial maintenance AI.
        Use ONLY the following manual excerpt to answer the user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s question.
        Manual Excerpt: {context}
        User Question: {question}
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;

        response = llm.generate_content(prompt)
        return {&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: response.text}

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="n"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:
    import uvicorn
    uvicorn.run(app, host=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, port=8080)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260508-yny-fastapi-no-rag_k7AedwVdEQ.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fa8obzvpnwshcdxyo8u6h.png" alt="yny-fastapi-no-rag" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Seed the AI "Brain" (&lt;code&gt;seed.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;To prove this works, we must inject an equipment manual into our database. Create &lt;code&gt;seed.py&lt;/code&gt;:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;google.generativeai&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;psycopg2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&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="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;manual_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
Maintenance Manual for PUMP-CENT-001:
Issue: Crackling noise (like marbles/gravel).
Diagnosis: Pump is experiencing cavitation due to low Net Positive Suction Head.
Action: Immediately throttle the discharge valve to reduce flow rate. Torque housing bolts to 45 Nm.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Embedding text via Gemini...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;embedding_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embed_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-embedding-001&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;manual_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_dimensionality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;768&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embedding_result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;embedding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Saving to PostgreSQL...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psycopg2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DB_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;cur&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSERT INTO manual_knowledge (product_code, section_title, text_chunk, embedding) VALUES (%s, %s, %s, %s)&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;PUMP-CENT-001&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;Troubleshooting: Noise&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;manual_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Vector Seeded Successfully!&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;Run &lt;code&gt;python seed.py&lt;/code&gt; once. Your database can now "think" about centrifugal pumps! Test your API by running &lt;code&gt;python main.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260508-yny-vector-embedding-seed_ul0IYCHtp.png" 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.amazonaws.com%2Fuploads%2Farticles%2Feh1awl4bz84cr0m7wksr.png" alt="yny-vector-embedding-seed" width="800" height="688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260508-yny-fastapi-rag-response_MfbEzAI2J.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fau7nk7x2x0wu1jw6i28j.png" alt="yny-fastapi-rag-response" width="800" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎨 Phase 4: The Frontend UI (React + Vite)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Initialize the App
&lt;/h3&gt;

&lt;p&gt;Go back to the root &lt;code&gt;yny-app&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest yny-ui &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react
&lt;span class="nb"&gt;cd &lt;/span&gt;yny-ui
npm &lt;span class="nb"&gt;install &lt;/span&gt;axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Build the Dashboard (&lt;code&gt;src/App.jsx&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Replace &lt;code&gt;App.jsx&lt;/code&gt; entirely. This UI will fetch inventory from &lt;code&gt;.NET&lt;/code&gt; and query &lt;code&gt;Python&lt;/code&gt; for AI troubleshooting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactMarkdown&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-markdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;remarkGfm&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;remark-gfm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuestion&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aiAnswer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAiAnswer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;ERP_API&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_ERP_API&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://erp-api-158766252751.us-central1.run.app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AI_API&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_AI_API&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://ai-api-158766252751.us-central1.run.app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ERP_API&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/api/products`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="s2"&gt;ERP API not running&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;askAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productCode&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;question&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="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;AI_API&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/troubleshoot`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;product_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;productCode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="nf"&gt;setAiAnswer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;answer&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;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setAiAnswer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error reaching AI service.&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;setLoading&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;system-ui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;900px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0 auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0056b3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Y&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;Y SaaS Dashboard&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;1. Live ERP Inventory: .NET Core (C#) + CloudSQL (PostgreSQL)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderCollapse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;collapse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#f4f4f4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Code&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Name&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Category&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Stock&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productCode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productCode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantityInStock&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&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;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantityInStock&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;hr&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2rem 0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;2. AI Domain Expert Agent: FastAPI (Python) + Gemma (Gemini)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid #ccc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fafafa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Target Equipment:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; PUMP-CENT-001&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; 
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; 
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setQuestion&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="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
          &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"e.g., Why is the pump sounding like gravel?"&lt;/span&gt; 
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.75rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid #ccc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;boxSizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border-box&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; 
          &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;askAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUMP-CENT-001&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
          &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.75rem 1.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0056b3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pointer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Analyzing Manuals...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Consult AI&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;aiAnswer&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#eef6ff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px solid #0056b3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0056b3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;YNY Tech Agent:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReactMarkdown&lt;/span&gt;
                &lt;span class="na"&gt;remarkPlugins&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;remarkGfm&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="na"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0056b3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.2rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.4rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0056b3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.3rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0056b3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#d9534f&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;em&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;em&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fontStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;italic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#666&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.8rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.8rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.8rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.8rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;li&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.6rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#f4f4f4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px 6px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monospace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#d9534f&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;blockquote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;blockquote&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;borderLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px solid #0056b3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;paddingLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.8rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.8rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#666&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;hr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;hr&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5rem 0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;aiAnswer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ReactMarkdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;npm run dev&lt;/code&gt; and test your local full-stack masterpiece!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260509-yny-dashboard_mOo65pzNO.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fbc34qnumyxgnfi3yup6h.png" alt="yny-react-vite-dashboard" width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Phase 5: Containerization &amp;amp; Cloud Run Deployment
&lt;/h2&gt;

&lt;p&gt;Now, we take our local code to the cloud. We will wrap our APIs in Docker containers and deploy them via Google Cloud Run (which scales to zero, saving you money!).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;The Cloud SQL Gotcha (Read This!):&lt;/strong&gt;&lt;br&gt;
Locally, you connected to Postgres via a TCP port (5432) and an IP address. In Google Cloud Run, best practice dictates you connect securely via a &lt;strong&gt;Unix domain socket&lt;/strong&gt;. &lt;br&gt;
We don't need a clunky proxy inside our Dockerfile. Google Cloud Run does this natively if we pass the right connection string!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're the project owner, grant yourself permissions first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud projects add-iam-policy-binding YOUR_PROJECT_ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;user:YourEmail@gmail.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;roles/cloudbuild.builds.editor,roles/cloudsql.client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1: Deploying the .NET API
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;/yny.Api&lt;/code&gt;, create a clean &lt;code&gt;Dockerfile&lt;/code&gt;:&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="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:8.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet publish &lt;span class="nt"&gt;-c&lt;/span&gt; Release &lt;span class="nt"&gt;-o&lt;/span&gt; out

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; mcr.microsoft.com/dotnet/aspnet:8.0&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /app/out .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; ASPNETCORE_URLS=http://+:8080&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["dotnet", "yny.Api.dll"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy it via your terminal (Replace &lt;code&gt;YOUR_PROJECT_ID&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Build and push the image to Google Container Registry&lt;/span&gt;
gcloud builds submit &lt;span class="nt"&gt;--tag&lt;/span&gt; gcr.io/YOUR_PROJECT_ID/erp-api

&lt;span class="c"&gt;# 2. Deploy to Cloud Run (Notice the new Unix Socket Connection String!)&lt;/span&gt;
gcloud run deploy erp-api &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; gcr.io/YOUR_PROJECT_ID/erp-api &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-central1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-unauthenticated&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--add-cloudsql-instances&lt;/span&gt; YOUR_PROJECT_ID:us-central1:yny-db-instance &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set-env-vars&lt;/span&gt; &lt;span class="nv"&gt;ConnectionStrings__DefaultConnection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Host=/cloudsql/YOUR_PROJECT_ID:us-central1:yny-db-instance;Database=postgres;Username=postgres;Password=YnySecurePass26;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Make sure to link your Cloud SQL instance to this Cloud Run service under the "Connections" tab in the GCP Console!)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Deploying the Python AI API
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;/yny.AI&lt;/code&gt;, create a &lt;code&gt;Dockerfile&lt;/code&gt;:&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="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy it (Remember to use your actual Gemini API key here, or better yet, use GCP Secret Manager in production):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud builds submit &lt;span class="nt"&gt;--tag&lt;/span&gt; gcr.io/YOUR_PROJECT_ID/ai-api

gcloud run deploy ai-api &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; gcr.io/YOUR_PROJECT_ID/ai-api &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-central1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-unauthenticated&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--add-cloudsql-instances&lt;/span&gt; YOUR_PROJECT_ID:us-central1:yny-db-instance &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set-env-vars&lt;/span&gt; &lt;span class="nv"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_API_KEY"&lt;/span&gt;,DB_URL&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"postgresql+psycopg2://postgres:YnySecurePass26@/postgres?host=/cloudsql/YOUR_PROJECT_ID:us-central1:yny-db-instance"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260509-yny-cloudsql-cloudrun_3THwWuTPh.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fiq69yjukybildj3zc48w.png" alt="yny-cloudsql-cloudrun" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Deploying the Frontend to Vercel
&lt;/h3&gt;

&lt;p&gt;Take note of the URLs Cloud Run just generated for you (e.g., &lt;code&gt;https://erp-api-xyz.run.app&lt;/code&gt; and &lt;code&gt;https://ai-api-xyz.run.app&lt;/code&gt;). &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push your &lt;code&gt;yny-ui&lt;/code&gt; code to GitHub.&lt;/li&gt;
&lt;li&gt;Log into &lt;a href="https://vercel.com/dashboard" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; and Import your repository.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Environment Variables&lt;/strong&gt;, add:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;VITE_ERP_API&lt;/code&gt; = &lt;code&gt;[Your Cloud Run .NET URL]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VITE_AI_API&lt;/code&gt; = &lt;code&gt;[Your Cloud Run Python URL]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Deploy&lt;/strong&gt;. Your UI is now live globally! Your UI will be live at: &lt;code&gt;https://yny-ui.vercel.app&lt;/code&gt; (or custom domain). Auto-deploys on every push to &lt;code&gt;main&lt;/code&gt; branch!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔄 Phase 6: Level-Up to CI/CD (Bonus)
&lt;/h2&gt;

&lt;p&gt;Tired of typing gcloud commands manually? Let GitHub deploy it for you. Create &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt; in your repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Microservices&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Auth GCP&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google-github-actions/auth@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;credentials_json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secrets.GCP_SA_KEY&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Cloud SDK&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google-github-actions/setup-gcloud@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy .NET API&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cd yny.Api&lt;/span&gt;
          &lt;span class="s"&gt;gcloud builds submit --tag gcr.io/${{ secrets.GCP_PROJECT_ID }}/erp-api&lt;/span&gt;
          &lt;span class="s"&gt;gcloud run deploy erp-api --image gcr.io/${{ secrets.GCP_PROJECT_ID }}/erp-api --region us-central1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(You will need to set &lt;code&gt;GCP_PROJECT_ID&lt;/code&gt; and a &lt;code&gt;GCP_SA_KEY&lt;/code&gt; in your GitHub Repository Settings -&amp;gt; Secrets).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎤 Phase 7: The Final Demo Script
&lt;/h2&gt;

&lt;p&gt;If you are showcasing this project to stakeholders, here is the exact narrative flow I recommend:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Show the Live Dashboard:&lt;/strong&gt; &lt;em&gt;"This is the Y&amp;amp;Y SaaS Dashboard. The top section is our .NET 8 ERP pulling live operational data directly from a PostgreSQL instance."&lt;/em&gt; Point out the real-time stock levels, specifically the out-of-stock valve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Setup the Incident:&lt;/strong&gt; &lt;em&gt;"Imagine a junior engineer is on the factory floor and hears a strange crackling noise coming from &lt;code&gt;PUMP-CENT-001&lt;/code&gt;."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute the Prompt:&lt;/strong&gt; Type: &lt;em&gt;"Why is the pump making a crackling noise like gravel and what should I do?"&lt;/em&gt; into the AI input and hit &lt;strong&gt;Consult AI&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explain the Magic:&lt;/strong&gt; &lt;em&gt;"Right now, our Python microservice is converting my question into a mathematical vector. It's querying the &lt;code&gt;pgvector&lt;/code&gt; database via Cosine Distance to retrieve the exact manufacturer maintenance manual excerpt, and passing that strict context to Google's Gemma model to synthesize a safe resolution."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Resolution:&lt;/strong&gt; The AI will output a clean, professional answer based &lt;em&gt;strictly&lt;/em&gt; on the manual we seeded (diagnosing cavitation and advising them to throttle the valve).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;By completing this build, you've successfully created a modern enterprise system. You separated concerns using microservices, connected to cloud databases, implemented the industry-standard RAG AI pattern, and utilized serverless cloud deployment. &lt;/p&gt;

&lt;p&gt;The gap between a "cool script" and an "enterprise system" is architecture. And you just built it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
    </item>
    <item>
      <title>Building a Systemic Autonomy Agent: OpenClaw + Gemma 4 &amp; TurboQuant on Raspberry Pi 4B</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Sat, 09 May 2026 06:20:02 +0000</pubDate>
      <link>https://dev.to/kheai/building-a-systemic-autonomy-agent-openclaw-gemma-4-turboquant-on-raspberry-pi-4b-49jk</link>
      <guid>https://dev.to/kheai/building-a-systemic-autonomy-agent-openclaw-gemma-4-turboquant-on-raspberry-pi-4b-49jk</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Write About Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’re reading this, you probably want to run a local, autonomous AI agent but might feel overwhelmed by the hardware requirements or complex software stacks. I was in exactly the same boat. I wanted to build an autonomous agent using OpenClaw, governed by the ethical and systemic framework of the KheAi Protocol, but I wanted it running entirely at the edge—specifically, on a Raspberry Pi 4B.&lt;/p&gt;

&lt;p&gt;After a lot of trial, error, and compiling, I successfully turned my Raspberry Pi 4B (8GB RAM, 120GB SSD boot) into a highly efficient edge brain running Gemma 4 (e2b) optimized with TurboQuant.&lt;/p&gt;

&lt;p&gt;Here is exactly how I did it, step-by-step, so you can follow along even if you are a total beginner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260419-openclaw-rpi-gemma4-turboquant-guide_luIuw0iV5.png" 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.amazonaws.com%2Fuploads%2Farticles%2F2ng8j0tktss742x6k77v.png" alt="Building a Systemic Autonomy Agent: OpenClaw + Gemma 4 &amp;amp; TurboQuant on Raspberry Pi 4B" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Master Plan: What We Are Building
&lt;/h2&gt;

&lt;p&gt;Before diving into the terminal commands, let's break down the architecture of what we are building:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Hardware (The Body):&lt;/strong&gt; A Raspberry Pi 4B (8GB RAM). Crucially, we are booting from a 120GB SSD, not a MicroSD card. If you want an agent that reads and writes data constantly, an SD card will bottleneck your speed and eventually corrupt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Mind (The LLM):&lt;/strong&gt; Gemma 4 E2B (specifically the &lt;code&gt;Q4_K_M&lt;/code&gt; quantization). This is a highly capable Small Language Model (SLM) fine-tuned for code execution and tool use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Optimizer (TurboQuant):&lt;/strong&gt; Running a modern LLM on 8GB of RAM is tight. We will use a custom branch of &lt;code&gt;llama.cpp&lt;/code&gt; featuring TurboQuant, which dynamically compresses the model's "short-term memory" (KV Cache), preventing our Pi from crashing during long conversations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Soul (KheAi Protocol):&lt;/strong&gt; Instead of a generic "hacking" persona, we will govern our OpenClaw agent using the KheAi Protocol—a framework for Systemic Autonomy. This gives the agent a structured, ethical, and goal-oriented operating system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking (Optional):&lt;/strong&gt; Tailscale for a Zero Trust Mesh Network. This allows secure, remote access to the OpenClaw dashboard and local terminal without exposing ports to the public internet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's get your edge agent alive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 1: Hardware &amp;amp; OS Foundation (The Body)
&lt;/h2&gt;

&lt;p&gt;Before we touch the AI, we need a stable "nervous system."&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1 Boot from SSD (Non-Negotiable)
&lt;/h3&gt;

&lt;p&gt;Running an autonomous agent on a MicroSD card will kill the card within weeks due to high read/write cycles and slow down the LLM's "thinking" time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Use Raspberry Pi Imager to flash &lt;a href="https://dev.to/posts/step-by-step-guide-to-setup-popebot-in-my-rpi"&gt;&lt;strong&gt;Raspberry Pi OS (64-bit)&lt;/strong&gt;&lt;/a&gt; onto your 120GB SSD.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization:&lt;/strong&gt; In the settings, enable SSH and set your username/password.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1.2 Thermal Management
&lt;/h3&gt;

&lt;p&gt;The Pi 4B will throttle (slow down) at 80°C, the "Brain" slows down, and OpenClaw might time out. Compiling LLMs and running inference will hit this within minutes. &lt;strong&gt;Requirement:&lt;/strong&gt; You &lt;strong&gt;must&lt;/strong&gt; use a heatsink and fan. Check your temp with &lt;code&gt;vcgencmd measure_temp&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.3 Tuning the OS
&lt;/h3&gt;

&lt;p&gt;Once logged in via SSH, optimize the memory and clock speed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="c"&gt;# Increase Swap to 4GB to handle model spikes&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dphys-swapfile swapoff
&lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/CONF_SWAPSIZE=100/CONF_SWAPSIZE=4096/'&lt;/span&gt; /etc/dphys-swapfile
&lt;span class="nb"&gt;sudo &lt;/span&gt;dphys-swapfile setup
&lt;span class="nb"&gt;sudo &lt;/span&gt;dphys-swapfile swapon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Phase 2: Compiling the Edge Brain (llama-cpp-turboquant)
&lt;/h2&gt;

&lt;p&gt;Standard LLM engines eat too much RAM. We are going to build a specialized version of &lt;code&gt;llama.cpp&lt;/code&gt; that uses &lt;strong&gt;TurboQuant KV Cache compression&lt;/strong&gt;. This allows Gemma 4 to handle long conversations without crashing the Pi.&lt;/p&gt;

&lt;p&gt;First, we need the tools to build the software. We will also install &lt;code&gt;libssl-dev&lt;/code&gt; to prevent any OpenSSL errors during the build process, and &lt;code&gt;libopenblas-dev&lt;/code&gt; for fast matrix math.&lt;/p&gt;

&lt;p&gt;Standard &lt;code&gt;llama.cpp&lt;/code&gt; builds might not have the specific cache compression flags we need. We will pull from a community fork and check out the exact branch where KV cache compression is being actively developed.&lt;/p&gt;

&lt;p&gt;The Raspberry Pi 4 uses a Cortex-A72 chip (ARMv8). The flag &lt;code&gt;-DGGML_NEON=ON&lt;/code&gt; is absolutely essential here—it tells the compiler to use the Pi's SIMD (Single Instruction, Multiple Data) instructions, which acts as the primary hardware accelerator for our math operations.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: Don't use newer flags like &lt;code&gt;ARM_KLEIDIAI&lt;/code&gt;; those are for ARMv9 and won't help you here).&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Build from Source
&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;# Install dependencies&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git cmake build-essential libopenblas-dev libssl-dev

&lt;span class="c"&gt;# Clone the TurboQuant-specific branch&lt;/span&gt;
git clone https://github.com/TheTom/llama-cpp-turboquant
&lt;span class="nb"&gt;cd &lt;/span&gt;llama-cpp-turboquant
git checkout feature/turboquant-kv-cache

&lt;span class="c"&gt;# Configure for Pi 4 (Cortex-A72 / NEON acceleration)&lt;/span&gt;
cmake &lt;span class="nt"&gt;-B&lt;/span&gt; build &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-DCMAKE_BUILD_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Release &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-DGGML_CPU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-DGGML_NATIVE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-DGGML_OPENBLAS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-DGGML_NEON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-DLLAMA_OPENSSL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON

&lt;span class="c"&gt;# Compile (This takes ~15 mins)&lt;/span&gt;
cmake &lt;span class="nt"&gt;--build&lt;/span&gt; build &lt;span class="nt"&gt;--config&lt;/span&gt; Release &lt;span class="nt"&gt;-j4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key Considerations for Raspberry Pi 4&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NEON Acceleration&lt;/strong&gt;: The &lt;code&gt;-DGGML_NEON=ON&lt;/code&gt; flag is essential for the Pi 4 to utilize its SIMD instructions for faster math. This is the primary hardware accelerator for ARMv8 chips like the one in the Raspberry Pi 4. Newer flags like &lt;code&gt;ARM_KLEIDIAI&lt;/code&gt; target ARMv9 and won't benefit your hardware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KV Cache Savings&lt;/strong&gt;: TurboQuant's primary benefit on a Pi 4 (especially 4GB models) is reducing the memory footprint of the KV cache, allowing you to use longer contexts without hitting swap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait for Compile&lt;/strong&gt;: Building on a Pi 4 can take 10–20 minutes. Ensure you have adequate cooling, as all 4 cores will be at 100% load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TurboQuant Branch&lt;/strong&gt;: &lt;strong&gt;&lt;code&gt;git checkout feature/turboquant-kv-cache&lt;/code&gt;&lt;/strong&gt;: This is the active development branch where the &lt;code&gt;--cache-type-k&lt;/code&gt; and &lt;code&gt;--cache-type-v&lt;/code&gt; flags are implemented.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TurboQuant Flags&lt;/strong&gt;: Once built, you can run your model with &lt;code&gt;-ctk turbo4 -ctv turbo4&lt;/code&gt; to significantly reduce RAM usage during long conversations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2iji9eus1v2okywnl923.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2F2iji9eus1v2okywnl923.jpg" alt="ssh rpi for llma.cpp" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Take a break.&lt;/strong&gt; Compiling on all 4 cores will push your Pi to 100% CPU load and can take 10 to 20 minutes. Ensure your Pi has decent cooling (a small fan or heatsink).&lt;/p&gt;

&lt;p&gt;Once finished, verify that the new cache types exist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./build/bin/llama-cli &lt;span class="nt"&gt;--help&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;cache-type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see &lt;code&gt;turbo4&lt;/code&gt; listed in the output, congratulations! Your edge engine is ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 3: Sourcing the Brain (Gemma 4 Q4_K_M)
&lt;/h2&gt;

&lt;p&gt;Next, we need the actual model weights. We will use the &lt;a href="https://huggingface.co/unsloth/gemma-4-E2B-it-GGUF" rel="noopener noreferrer"&gt;&lt;code&gt;gemma-4-E2B-it-GGUF&lt;/code&gt;&lt;/a&gt; model.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Quick Lesson on Quantization (Why we use Q4_K_M + TurboQuant)
&lt;/h3&gt;

&lt;p&gt;Before you download, it is crucial to understand the two different types of "shrinking" we are doing to make this fit on a Pi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Weight Quantization (&lt;code&gt;Q4_K_M.gguf&lt;/code&gt;):&lt;/strong&gt; This compresses the model's &lt;strong&gt;permanent weights&lt;/strong&gt; (its long-term memory). The file you download is already shrunk from 16-bit to roughly 4-bit. This is what allows a multi-billion parameter model to sit comfortably on your SD card or SSD.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KV Cache Quantization (TurboQuant):&lt;/strong&gt; This compresses the model's &lt;strong&gt;short-term memory&lt;/strong&gt; (the scratchpad it uses &lt;em&gt;while&lt;/em&gt; you are chatting). TurboQuant isn't a file you download; it’s an active efficiency mode you toggle on when running the server to stop RAM usage from ballooning as context grows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Option 1: Install via OpenSSL Development Headers (ODHs)
&lt;/h3&gt;

&lt;p&gt;Run this in your &lt;code&gt;llama-cpp-turboquant&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./build/bin/llama-cli &lt;span class="nt"&gt;-hf&lt;/span&gt; unsloth/gemma-4-E2B-it-GGUF:Q4_K_M
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 2: Download the Model Manually
&lt;/h3&gt;

&lt;p&gt;Alternatively,  to avoid messing with Python scripts or SSL library issues, let's just grab the file directly via the terminal using &lt;code&gt;wget&lt;/code&gt; (or &lt;code&gt;curl&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://huggingface.co/unsloth/gemma-4-E2B-it-GGUF/resolve/main/gemma-4-E2B-it-Q4_K_M.gguf &lt;span class="nt"&gt;-O&lt;/span&gt; models/gemma-4-E2B-it-Q4_K_M.gguf

curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://huggingface.co/unsloth/Qwen3.5-0.8B-GGUF/resolve/main/Qwen3.5-0.8B-Q4_K_S.gguf &lt;span class="nt"&gt;-o&lt;/span&gt; models/Qwen3.5-0.8B-Q4_K_S.gguf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(If you prefer Qwen3.5 as a lighter alternative, you can swap the URL for a &lt;a href="///posts/run-popebot-local-qwen-3.5-2b-rpi"&gt;Qwen 0.8B GGUF&lt;/a&gt; file, but Gemma 4 E2B is specifically tuned for agentic tasks).&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Local Test Run
&lt;/h3&gt;

&lt;p&gt;Before hooking this up to OpenClaw, let's test it in the command line using &lt;code&gt;llama-cli&lt;/code&gt;. We will pass in all our optimization flags. Either via &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ODHs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./build/bin/llama-cli &lt;span class="nt"&gt;-hf&lt;/span&gt; unsloth/gemma-4-E2B-it-GGUF:Q4_K_M &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; 4096 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-b&lt;/span&gt; 128 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--temp&lt;/span&gt; 0.1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--chat-template-kwargs&lt;/span&gt; &lt;span class="s1"&gt;'{"enable_thinking":false}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-k&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-v&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fa&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-sys&lt;/span&gt; &lt;span class="s2"&gt;"You are a Stoic logic engine. Be concise."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-cnv&lt;/span&gt; &lt;span class="nt"&gt;--color&lt;/span&gt; auto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Manual&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./build/bin/llama-cli &lt;span class="nt"&gt;-m&lt;/span&gt; models/gemma-4-E2B-it-Q4_K_M.gguf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; 4096 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-b&lt;/span&gt; 128 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--temp&lt;/span&gt; 0.1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-k&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-v&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fa&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-sys&lt;/span&gt; &lt;span class="s2"&gt;"You are an autonomous agent operating under the KheAi Protocol. Be concise."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-cnv&lt;/span&gt; &lt;span class="nt"&gt;--color&lt;/span&gt; auto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./build/bin/llama-cli &lt;span class="nt"&gt;-m&lt;/span&gt; models/Qwen3.5-0.8B-Q4_K_S.gguf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; 4096 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-b&lt;/span&gt; 128 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--temp&lt;/span&gt; 0.1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--reasoning-budget&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-k&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-v&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fa&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-sys&lt;/span&gt; &lt;span class="s2"&gt;"Be concise."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-cnv&lt;/span&gt; &lt;span class="nt"&gt;--color&lt;/span&gt; auto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Let’s break down the magic flags:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-t 4&lt;/code&gt;: Uses all 4 CPU threads.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-c 4096&lt;/code&gt;: Gives the model a 4K context window (plenty for agent logs). Below 1,000 tokens, TurboQuant's memory savings are negligible. The 4K mark is exactly where compressing the KV cache to 4-bits starts to dramatically save RAM, keeping the Node.js OpenClaw process and the OS from fighting over the Pi's 8GB limit.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cache-type-k turbo4&lt;/code&gt; &amp;amp; &lt;code&gt;--cache-type-v turbo4&lt;/code&gt;: This is TurboQuant in action! It compresses the Keys and Values in the cache to 4-bit polar coordinates.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-fa on&lt;/code&gt; (Flash Attention): &lt;strong&gt;Crucial.&lt;/strong&gt; TurboQuant requires Flash Attention to be enabled to function correctly with the compressed blocks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--reasoning-budget 0&lt;/code&gt;: Forces the model to skip lengthy internal monologues and looping, outputting direct, actionable responses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Spinning up the Server for OpenClaw
&lt;/h3&gt;

&lt;p&gt;OpenClaw needs an API to talk to. We will launch &lt;code&gt;llama-server&lt;/code&gt; to act as an OpenAI-compatible backend, hosted directly on your Pi.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./build/bin/llama-server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-m&lt;/span&gt; models/gemma-4-E2B-it-Q4_K_M.gguf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; 4096 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-b&lt;/span&gt; 128 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-k&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-v&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fa&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--api-key&lt;/span&gt; &lt;span class="s2"&gt;"local-pi-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your Raspberry Pi is now acting as a dedicated, local AI server. It is listening on port &lt;code&gt;8080&lt;/code&gt; and is accessible from any machine on your local network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 4: The OpenClaw Setup &amp;amp; Onboarding (The Hands)
&lt;/h2&gt;

&lt;p&gt;OpenClaw is a Node.js-based autonomous framework. We will use the official one-liner but then manually "onboard" it to our local brain.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://openclaw.ai/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.2 The Onboarding Wizard (Crucial Step)
&lt;/h3&gt;

&lt;p&gt;This is where we connect the framework to our Pi's local server. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw onboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Follow these specific inputs for local autonomy:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Provider:&lt;/strong&gt; Select &lt;code&gt;OpenAI Compatible&lt;/code&gt; (Since &lt;code&gt;llama-server&lt;/code&gt; mimics this).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Key:&lt;/strong&gt; Enter &lt;code&gt;local-pi-key&lt;/code&gt; (or anything, it’s local).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base URL:&lt;/strong&gt; &lt;code&gt;http://127.0.0.1:8080/v1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; &lt;code&gt;gemma-4-E2B-it-Q4_K_M&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools:&lt;/strong&gt; Enable &lt;code&gt;Terminal&lt;/code&gt; and &lt;code&gt;Filesystem&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox:&lt;/strong&gt; Since we are using Gemma 4 &lt;strong&gt;E2B&lt;/strong&gt;, you should ideally provide an &lt;a href="https://e2b.dev/" rel="noopener noreferrer"&gt;E2B.dev&lt;/a&gt; API key if you want the agent to execute code in a secure, cloud-hosted sandbox. If you want it 100% local, select &lt;code&gt;Local Terminal&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Phase 5: Activating the KheAi Protocol (The Soul)
&lt;/h2&gt;

&lt;p&gt;We don't want a generic assistant. We want a systemic autonomous agent. We achieve this by overriding the OpenClaw "Persona."&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Navigate to your OpenClaw config directory: &lt;code&gt;cd ~/.openclaw&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create/Edit your system prompt: &lt;code&gt;nano SOUL.md&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste the &lt;a href="https://www.kheai.com/posts/kheai-protocol-systemic-autonomy-architecture" rel="noopener noreferrer"&gt;&lt;strong&gt;KheAi Protocol Architecture&lt;/strong&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;   ## KheAi Protocol v1.0

   &lt;span class="gs"&gt;**Core Identity:**&lt;/span&gt; You are a Systemic Autonomy Agent.

   &lt;span class="gs"&gt;**Operational Framework (OODA):**&lt;/span&gt; &amp;gt; - &lt;span class="gs"&gt;**Observe:**&lt;/span&gt; Scan the local environment/files.
&lt;span class="p"&gt;
   -&lt;/span&gt; &lt;span class="gs"&gt;**Orient:**&lt;/span&gt; Check Pi resource constraints (RAM/Temp).
&lt;span class="p"&gt;   -&lt;/span&gt; &lt;span class="gs"&gt;**Decide:**&lt;/span&gt; Choose the tool that uses the least energy.
&lt;span class="p"&gt;   -&lt;/span&gt; &lt;span class="gs"&gt;**Act:**&lt;/span&gt; Execute and verify.

   &lt;span class="gs"&gt;**Constraint:**&lt;/span&gt; You are running on a Raspberry Pi 4. Be concise. Do not loop. Use TurboQuant awareness for long contexts.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the KheAi OODA (Observe, Orient, Decide, Act) constraint, a generic model might hallucinate tools or try to write long-winded python scripts. The protocol forces it to act like a machine, not a chatbot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 6: Launching the System Again
&lt;/h2&gt;

&lt;p&gt;You need two terminal windows (or use &lt;code&gt;tmux&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Terminal 1: The Brain (Server)
&lt;/h3&gt;

&lt;p&gt;Start the model with the TurboQuant flags to compress the memory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./build/bin/llama-server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-m&lt;/span&gt; models/gemma-4-E2B-it-Q4_K_M.gguf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; 4096 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-k&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-type-v&lt;/span&gt; turbo4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--reasoning-budget&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fa&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: &lt;code&gt;--cache-type-k turbo4&lt;/code&gt; shrinks the "short-term memory" by 4x so you don't run out of 8GB RAM.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Terminal 2: The Framework (OpenClaw)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Phase 7: Remote Access with Tailscale
&lt;/h2&gt;

&lt;p&gt;Once your Raspberry Pi is running an autonomous agent, you don’t want it tied to a monitor and keyboard on your desk. You want it running "headless" (plugged into power and network only) in a closet or next to your router. &lt;/p&gt;

&lt;p&gt;However, exposing your local Pi to the public internet via port forwarding is a massive security risk. Instead, we will use Tailscale to create a Zero Trust Mesh Network. This creates a secure, private tunnel between your laptop/phone and your Pi, allowing you to SSH into it or access OpenClaw from a coffee shop halfway across the world.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.1 Installation
&lt;/h3&gt;

&lt;p&gt;Run this simple one-liner on your Pi to download and install Tailscale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://tailscale.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7.2 Activation &amp;amp; Authentication
&lt;/h3&gt;

&lt;p&gt;Once installed, bring the network interface up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;tailscale up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will output a URL. Copy and paste that URL into a browser on your main computer to authenticate the Pi with your Tailscale account (it's free for personal use). &lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;tailscale ip -4&lt;/code&gt; to get your Pi’s new secure IP address. You can now securely SSH into your Pi (&lt;code&gt;ssh pi@[tailscale-ip]&lt;/code&gt;) or access your agent dashboards remotely without opening a single port on your home router.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 8: Hybrid Cloud-Edge (Switching to the Gemini API)
&lt;/h2&gt;

&lt;p&gt;Running everything locally on a Pi is an incredible achievement for privacy and independence. But what if your agent encounters a task that requires massive reasoning power, deep web research, or complex code generation that Gemma 4 Q4_K_M struggles with? &lt;/p&gt;

&lt;p&gt;This is where a &lt;strong&gt;Hybrid Architecture&lt;/strong&gt; shines. You use the local edge model as your primary driver for simple, continuous tasks, and switch to a frontier cloud model like the Gemini API for the "heavy lifting." &lt;/p&gt;

&lt;h3&gt;
  
  
  The Strategy: Local for Actions, Gemini for Deep Reasoning
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary (Local Gemma 4):&lt;/strong&gt; Use this for file scanning, basic terminal commands, navigating the OS, and formatting data. It is free, private, and fast enough for OODA loop execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback/Heavy Lifting (Gemini API):&lt;/strong&gt; Route tasks here when the agent needs to write complex Python scripts, analyze large datasets, or process visual information. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.1 Getting the Gemini API Key
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt; and sign in.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Get API Key&lt;/strong&gt; and generate a new key. Keep this secure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  8.2 Re-configuring OpenClaw
&lt;/h3&gt;

&lt;p&gt;To switch your agent's brain over to Gemini, you simply need to run the onboarding wizard again (or edit your OpenClaw config file directly).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw onboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Follow these inputs for the Cloud-Heavy setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Provider:&lt;/strong&gt; Select &lt;code&gt;Google&lt;/code&gt; or &lt;code&gt;Gemini&lt;/code&gt; (depending on your OpenClaw version).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Key:&lt;/strong&gt; Paste your Gemini API key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; Select &lt;code&gt;gemini-2.5-pro&lt;/code&gt; (for maximum reasoning and coding capabilities) or &lt;code&gt;gemini-2.5-flash&lt;/code&gt; (for high speed and lower cost).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools &amp;amp; Sandbox:&lt;/strong&gt; Keep these the same as Phase 4.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By swapping the provider, your agent instantly upgrades its cognitive capabilities while still utilizing the Pi as its physical "body" to execute terminal commands and interact with the local environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Building an autonomous agent entirely at the edge used to require expensive gaming laptops. By combining the affordability of a Raspberry Pi 4, the tailored intelligence of Gemma 4 E2B, and the incredible memory-saving techniques of TurboQuant, you now have a self-contained AI brain sitting on your desk.&lt;/p&gt;

&lt;p&gt;It takes patience to compile and tune, but once that server says "HTTP server listening," the feeling of having a localized, private, and fully autonomous intelligence under your control is unmatched.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team Submissions&lt;/strong&gt;: &lt;a class="mentioned-user" href="https://dev.to/kheai"&gt;@kheai&lt;/a&gt; &lt;a class="mentioned-user" href="https://dev.to/yeemun122"&gt;@yeemun122&lt;/a&gt; &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
      <category>kheai</category>
    </item>
    <item>
      <title>AI-Powered ERP System with Gemma 26B MoE</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Fri, 08 May 2026 18:49:02 +0000</pubDate>
      <link>https://dev.to/kheai/ai-powered-erp-system-with-gemma-26b-moe-2l5i</link>
      <guid>https://dev.to/kheai/ai-powered-erp-system-with-gemma-26b-moe-2l5i</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Build with Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdq4oqiihrjp4vn1t3zoz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdq4oqiihrjp4vn1t3zoz.png" alt="AI-Powered ERP System with Gemma 26B MoE" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Don’t just track your equipment—troubleshoot it.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;I built the &lt;strong&gt;Y&amp;amp;Y App&lt;/strong&gt;: an industrial-grade, microservices-based SaaS that merges live ERP inventory management with a state-of-the-art &lt;strong&gt;AI Domain-Expert Agent&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260509-yny-dashboard_mOo65pzNO.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fbc34qnumyxgnfi3yup6h.png" alt="yny-react-vite-dashboard" width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Factory floors and industrial sites suffer from massive financial losses during equipment downtime. When machinery fails, junior engineers often waste critical hours digging through dense, hundreds-of-pages-long OEM manuals to diagnose obscure faults. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; I engineered a system where a user can view their live inventory and literally ask the system, &lt;em&gt;"Why is PUMP-CENT-001 making a crackling noise like gravel?"&lt;/em&gt; The app uses a highly structured Retrieval-Augmented Generation (RAG) pipeline to instantly retrieve the exact manufacturer manual excerpt and synthesize an accurate, safe resolution. &lt;/p&gt;

&lt;p&gt;By separating concerns into a strict microservices architecture—.NET 8 for the ERP business logic, Python (FastAPI) for the AI brain, and React for the UI—I've created an enterprise-ready blueprint that is scalable, maintainable, and blazingly fast.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260509-yny-workflow_bFOldGiR_.png" 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.amazonaws.com%2Fuploads%2Farticles%2Ffo2h4yhz5n993t3c4yym.png" alt="yny-workflow" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260509-yny-cloudsql-cloudrun_3THwWuTPh.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fiq69yjukybildj3zc48w.png" alt="yny-cloudsql-cloudrun" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Live Web App:&lt;/strong&gt; &lt;a href="https://yny-ui.vercel.app/" rel="noopener noreferrer"&gt;Play with the Y&amp;amp;Y App on Vercel&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Video Walkthrough
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pure Gemini API&lt;/strong&gt;&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/FsEYWDAcwsw"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vertex AI&lt;/strong&gt; &lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/JHX0fRmJuW4"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kheAI" rel="noopener noreferrer"&gt;
        kheAI
      &lt;/a&gt; / &lt;a href="https://github.com/kheAI/yny-app" rel="noopener noreferrer"&gt;
        yny-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🏗️ Y&amp;amp;Y App – AI-Powered Industrial ERP&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://yny-ui.vercel.app/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d1d955c50a2cf960d0e0c391268d22a8d1771472c7f839375f5c9f42a9a58bee/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6976652d44656d6f2d627269676874677265656e2e7376673f7374796c653d666f722d7468652d6261646765" alt="Live Demo"&gt;&lt;/a&gt;
&lt;a href="https://www.youtube.com/watch?v=JHX0fRmJuW4" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/f3fec6f453a3c18e1fd3145ea16b368719f761601ea58dccd013997756a56364/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f596f75547562652d566964656f5f44656d6f2d7265642e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d796f7574756265" alt="YouTube"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An industrial-grade, microservices-based SaaS that combines live ERP inventory management with a state-of-the-art &lt;strong&gt;AI Domain-Expert Agent&lt;/strong&gt; capable of diagnosing machinery issues in real-time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Building monolithic apps is a thing of the past. Y&amp;amp;Y App showcases a robust, strictly decoupled &lt;strong&gt;Microservices Architecture&lt;/strong&gt;, separating enterprise business logic (inventory) from complex AI workflows (Retrieval-Augmented Generation), all unified under a blazing-fast React frontend.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ The Elevator Pitch&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Don't just track your equipment—&lt;em&gt;troubleshoot it&lt;/em&gt;. Y&amp;amp;Y App uses a &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt; pipeline powered by Google's Gemini APIs and PostgreSQL &lt;code&gt;pgvector&lt;/code&gt;. When a user reports a strange noise from a pump, the AI doesn't guess; it performs a vector similarity search to retrieve the exact manufacturer maintenance manual and synthesizes a safe, factual resolution.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Key Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Microservices Architecture:&lt;/strong&gt; Independent scaling for UI, ERP, and AI logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise-Grade ERP API:&lt;/strong&gt; Built with &lt;strong&gt;.NET 8 Minimal&lt;/strong&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kheAI/yny-app" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Used Gemma 4
&lt;/h2&gt;

&lt;p&gt;To make this industrial AI reliable and fast, I built a custom Retrieval-Augmented Generation (RAG) pipeline powered by Gemma 4. &lt;/p&gt;

&lt;p&gt;Here is exactly how I integrated the models into my Python microservice:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Brain: &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
I chose the &lt;strong&gt;Gemma 4 26B MoE (Mixture-of-Experts)&lt;/strong&gt; model for the core reasoning engine. In industrial environments, precision and speed are non-negotiable. If a centrifugal pump is cavitating, an engineer needs the remediation steps &lt;em&gt;immediately&lt;/em&gt; before catastrophic failure occurs. &lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; utilizes an MoE architecture, it provides the deep intelligence and reasoning capabilities of a massive 26-billion parameter model, but achieves &lt;strong&gt;ultra-low latency&lt;/strong&gt; by only activating a fraction of its parameters (~4B) during inference. This was the absolute perfect fit for a real-time conversational agent where users are waiting on the UI for critical answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Memory: &lt;code&gt;gemini-embedding-001&lt;/code&gt; and PostgreSQL &lt;code&gt;pgvector&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
To prevent hallucinations—which are dangerous in industrial maintenance—the AI is strictly grounded in actual equipment manuals. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When a user asks a question, my Python FastAPI service uses the &lt;code&gt;gemini-embedding-001&lt;/code&gt; model to turn the text into a 768-dimensional mathematical vector. &lt;/li&gt;
&lt;li&gt;  I then run a Cosine Distance (&lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt;) SQL query against my Google Cloud SQL PostgreSQL database (using the &lt;code&gt;pgvector&lt;/code&gt; extension) to find the most mathematically similar equipment manual chunk.&lt;/li&gt;
&lt;li&gt;  Finally, that strict context is passed via prompt engineering to the &lt;strong&gt;Gemma 4&lt;/strong&gt; model, instructing it to act as an expert industrial maintenance AI and synthesize an answer &lt;em&gt;only&lt;/em&gt; using the provided manual.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt; A lightning-fast, highly intelligent, hallucination-free AI assistant that turns an overwhelming physical manual into an interactive, real-time problem solver.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260509-yny-gemini-api-rate-limit_nqq-NibK1.png" 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.amazonaws.com%2Fuploads%2Farticles%2F3bihtggga9soibxpb0u3.png" alt="yny-gemini-api-rate-limit" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;If you are showcasing this project to stakeholders, here is the exact narrative flow I recommend:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Show the Live Dashboard:&lt;/strong&gt; &lt;em&gt;"This is the Y&amp;amp;Y SaaS Dashboard. The top section is our .NET 8 ERP pulling live operational data directly from a PostgreSQL instance."&lt;/em&gt; Point out the real-time stock levels, specifically the out-of-stock valve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Setup the Incident:&lt;/strong&gt; &lt;em&gt;"Imagine a junior engineer is on the factory floor and hears a strange crackling noise coming from &lt;code&gt;PUMP-CENT-001&lt;/code&gt;."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute the Prompt:&lt;/strong&gt; Type: &lt;em&gt;"Why is the pump making a crackling noise like gravel and what should I do?"&lt;/em&gt; into the AI input and hit &lt;strong&gt;Consult AI&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explain the Magic:&lt;/strong&gt; &lt;em&gt;"Right now, our Python microservice is converting my question into a mathematical vector. It's querying the &lt;code&gt;pgvector&lt;/code&gt; database via Cosine Distance to retrieve the exact manufacturer maintenance manual excerpt, and passing that strict context to Google's Gemma model to synthesize a safe resolution."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Resolution:&lt;/strong&gt; The AI will output a clean, professional answer based &lt;em&gt;strictly&lt;/em&gt; on the manual we seeded (diagnosing cavitation and advising them to throttle the valve).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Team Submissions&lt;/strong&gt;: &lt;a class="mentioned-user" href="https://dev.to/kheai"&gt;@kheai&lt;/a&gt; &lt;a class="mentioned-user" href="https://dev.to/yeemun122"&gt;@yeemun122&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
      <category>kheai</category>
    </item>
    <item>
      <title>Blaze 3 Unofficial Simple Todos Tutorial with Meteor 3.4.1 + Rspack + PicoCSS</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Fri, 08 May 2026 12:02:03 +0000</pubDate>
      <link>https://dev.to/kheai/blaze-3-unofficial-simple-todos-tutorial-with-meteor-341-rspack-picocss-52n7</link>
      <guid>https://dev.to/kheai/blaze-3-unofficial-simple-todos-tutorial-with-meteor-341-rspack-picocss-52n7</guid>
      <description>&lt;p&gt;Welcome! In this tutorial, we will create a simple To-Do app using &lt;a href="https://www.blazejs.org/" rel="noopener noreferrer"&gt;Blaze&lt;/a&gt; and Meteor 3.4.1.&lt;/p&gt;

&lt;p&gt;Blaze is Meteor's original, deeply integrated UI framework. It uses an easy-to-learn, Handlebars-like template syntax. Compared to traditional tools, Blaze eliminates the need to manually update the DOM when your database changes. Instead, it integrates directly with Meteor's transparent reactivity. Change a document in your database, and the UI updates instantly.&lt;/p&gt;

&lt;p&gt;With Meteor, a single developer can build a fully functional, real-time app in the time it takes a team of architects to decide on their communication protocols. Let's start building.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/tutorial/260508-meteor-blaze-todos-picocss_TVHhkNguw.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fef8mt8fsi8zlna6hs7kb.png" alt="Blaze 3 Unofficial Simple Todos Tutorial with Meteor 3.4.1 + Rspack + PicoCSS" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PS: &lt;em&gt;Tutorial originally adapted from the official&lt;/em&gt; &lt;a href="https://docs.meteor.com/tutorials/blaze/" rel="noopener noreferrer"&gt;Meteor Blaze Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Github Repo: &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/kheAI" rel="noopener noreferrer"&gt;
        kheAI
      &lt;/a&gt; / &lt;a href="https://github.com/kheAI/todos-app" rel="noopener noreferrer"&gt;
        todos-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;📝 Simple Todos (Meteor 3 + Blaze)&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://meteor.com" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/574d72bd8a08784ad91e633e78721f9d2cbdde6337911fa99c4053b32095a9f6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d6574656f722d332e342e312d7265643f6c6f676f3d6d6574656f72" alt="Meteor Version"&gt;&lt;/a&gt;
&lt;a href="https://github.com/kheAI/todos-app#" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/9de091cd711a25e148027ccf20487015ae6ee7fd63583a80a8c663a9d4b5c803/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46726f6e74656e642d426c617a652d6f72616e6765" alt="Frontend"&gt;&lt;/a&gt;
&lt;a href="https://github.com/kheAI/todos-app#" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c32bbad0f07e58b78121062d527ed984e5ae89a221bfca692647890e6c86c8f1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f42756e646c65722d52737061636b2d79656c6c6f77" alt="Bundler"&gt;&lt;/a&gt;
&lt;a href="https://github.com/kheAI/todos-app#" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/88452814468c4f6d0a814b0c23ae02a80a13ba1a6353f67c09f4cdf822bc5bd5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4353532d5069636f4353532d626c7565" alt="CSS Framework"&gt;&lt;/a&gt;
&lt;a href="https://kheai-todo.sandbox.galaxycloud.app/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/86e871c690ba9150223d03ca0438f6e79117d26be5f6704c31f51961c5bff260/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4465706c6f7965642d4d6574656f725f47616c6178792d737563636573733f6c6f676f3d6d6574656f72" alt="Deployed on Galaxy"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A reactive, full-stack To-Do application built to demonstrate the power and speed of &lt;strong&gt;Meteor 3.4.1&lt;/strong&gt; using its native &lt;strong&gt;Blaze&lt;/strong&gt; templating engine.&lt;/p&gt;
&lt;p&gt;This project showcases modern Meteor features including &lt;code&gt;Rspack&lt;/code&gt; for lightning-fast bundling, fully asynchronous database operations (&lt;code&gt;Async/Await&lt;/code&gt;), user authentication, and Optimistic UI.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Live Demo&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://kheai-todo.sandbox.galaxycloud.app/" rel="nofollow noopener noreferrer"&gt;Play with the live app here!&lt;/a&gt;&lt;/strong&gt; &lt;em&gt;(Deployed via Meteor Galaxy)&lt;/em&gt;&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;Real-time Reactivity:&lt;/strong&gt; Changes in the database are instantly reflected in the UI without manual DOM manipulation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimistic UI:&lt;/strong&gt; When a user checks or deletes a task, the UI updates instantly (zero latency) while the server processes the request securely in the background.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Authentication:&lt;/strong&gt; Built-in secure login system using &lt;code&gt;accounts-password&lt;/code&gt; and &lt;code&gt;bcrypt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Security:&lt;/strong&gt; Strict data-flow control using Meteor Publications/Subscriptions and secure Remote Procedure Calls (Meteor Methods).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Management:&lt;/strong&gt; Client-side state filtering (hiding completed tasks) managed via &lt;code&gt;reactive-dict&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic Styling:&lt;/strong&gt; Zero-config, responsive…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kheAI/todos-app" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Aue-JcBxB3o"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Updated Full step-by-step Tutorial had been moved to &lt;a href="https://www.kheai.com/posts/6001-meteor-todo-tutorial-unofficial/" rel="noopener noreferrer"&gt;https://www.kheai.com/posts/6001-meteor-todo-tutorial-unofficial/&lt;/a&gt; &lt;/p&gt;

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

&lt;p&gt;You have just built a reactive, full-stack application with a real database, user authentication, and secure remote procedure calls. What you've learned here applies to applications of massive scale. Welcome to the Meteor ecosystem!&lt;/p&gt;

</description>
      <category>meteor</category>
      <category>kheai</category>
      <category>fullstack</category>
      <category>webdev</category>
    </item>
    <item>
      <title>HuntOS: The Autonomous Enterprise Sentinel — A Production-Grade Agentic Swarm on the Next '26 Stack</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Sun, 26 Apr 2026 17:16:09 +0000</pubDate>
      <link>https://dev.to/kheai/huntos-the-autonomous-enterprise-sentinel-a-production-grade-agentic-swarm-on-the-next-26-stack-5h7</link>
      <guid>https://dev.to/kheai/huntos-the-autonomous-enterprise-sentinel-a-production-grade-agentic-swarm-on-the-next-26-stack-5h7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://www.google.com/url?sa=E&amp;amp;q=https%3A%2F%2Fdev.to%2Fchallenges%2Fgoogle-cloud-next-2026-04-22"&gt;Google Cloud NEXT Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;The era of vibe-coding fragile chatbot prototypes is over. Thanks to extensive research into the announcements at &lt;a href="https://www.google.com/url?sa=E&amp;amp;q=https%3A%2F%2Fdev.to%2Fyeemun122%2Fthe-end-of-the-prototype-trap-real-engineering-lessons-from-google-cloud-next-26-347f"&gt;Google Cloud Next '26&lt;/a&gt;, I have combined the most impactful platform updates into one cohesive architecture. This project demonstrates the full &lt;strong&gt;Agentic Enterprise&lt;/strong&gt; stack in action—systems that don't just chat, but take verified, physical business actions.&lt;/p&gt;

&lt;p&gt;To pressure-test this new stack, I built &lt;strong&gt;HuntOS&lt;/strong&gt;: an autonomous, cross-cloud security swarm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260427-huntos-sentinel-dev_aUSGyGujt.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fo40p1guxdxeaedw9xod4.png" alt="HuntOS: The Autonomous Enterprise Sentinel. Building the First Production-Grade Agentic Swarm on the Next '26 Stack" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HuntOS is an Agent-to-Agent (A2A) workforce designed to hunt anomalies across disconnected environments. It ingests messy unstructured "dark data" (like AWS S3 logs), cross-references anomalies against a secure Spanner Graph, and orchestrates a swarm of Gemini 3.1 Pro agents to draft, critique, and deploy Terraform remediation scripts. All with zero human intervention and enterprise-grade egress security.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Next '26 Equation:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;(Cross-Cloud Lakehouse × Knowledge Catalog) + MCP Server + (A2A Swarm @ TPU v8i) + (Agent Gateway + Model Armor) + Vertex AI Memory Bank = Production-Ready Agentic OS&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;💡 &lt;strong&gt;For the Enterprise CISO:&lt;/strong&gt; Currently, remediating a cross-cloud leak takes hours of human investigation, Jira tickets, and manual Terraform patching. HuntOS reduces Time-To-Remediate (TTR) from hours to under 3 seconds—without requiring you to move your raw AWS logs into Google Cloud, and without exposing your database credentials directly to an LLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo &amp;amp; Code
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/xFtAdnzOE8M"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source Code:&lt;/strong&gt; &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/kheAI" rel="noopener noreferrer"&gt;
        kheAI
      &lt;/a&gt; / &lt;a href="https://github.com/kheAI/huntos" rel="noopener noreferrer"&gt;
        huntos
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;HuntOS: The Autonomous Enterprise Sentinel&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260427-huntos-sentinel-dev_aUSGyGujt.png" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8a1b6963548ea59d6ab2040671036a5d6d14279fd7c19d61b83419ce71c8ec99/68747470733a2f2f696b2e696d6167656b69742e696f2f6d6f6f70742f6b686561692f61692f3236303432372d68756e746f732d73656e74696e656c2d6465765f615553477947756a742e706e67" alt="HuntOS-Banner"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HuntOS&lt;/strong&gt; is an autonomous, cross-cloud security swarm built to demonstrate the full &lt;strong&gt;Agentic Enterprise&lt;/strong&gt; stack announced at Google Cloud Next '26.&lt;/p&gt;
&lt;p&gt;It transitions from simple "fragile chatbot prototypes" to "Agentic AI" by detecting anomalies in "dark data" (messy AWS S3 logs), verifying them via a secure Spanner Graph, and orchestrating a swarm of Gemini 3.1 Pro agents to draft, critique, and deploy Terraform remediation scripts. All with zero human intervention and enterprise-grade egress security.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Next '26 Mega-Product Equation&lt;/strong&gt;
(Cross-Cloud Lakehouse × Knowledge Catalog) + MCP Server + (A2A Swarm @ TPU v8i) + (Agent Gateway + Model Armor) + Vertex AI Memory Bank = Production-Ready Agentic OS&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚦 Architectural Breakdown Matrix&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;System Requirement&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Next '26 Execution Method&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Primary Technology&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Function (The Sentinel Value)&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Gravity / Ingestion&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cross-Cloud Connectivity&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cross-Cloud Lakehouse &amp;amp; Knowledge Catalog&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Indexes unstructured "dark data" (PDFs/Logs) in-place across AWS and GCP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kheAI/huntos" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The Architecture: Reversing the Prototype Trap
&lt;/h2&gt;

&lt;p&gt;To win in modern infrastructure, you have to architect for the system, not just the AI. AI cannot verify your identity or configure cross-cloud IAM roles. You must lay the physical groundwork first.&lt;/p&gt;

&lt;p&gt;Here is the architectural breakdown of how I wired the Next '26 stack together:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260427-huntos-dashboard_d09KMTNGV.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fs4tog2g16s299ufqk9d0.png" alt="huntos-dashboard" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260427-huntos-view-fix_59uSsTQyb.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fph43c15e9twf3s3urqgn.png" alt="huntos-view-fix" width="800" height="705"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Conquering Data Gravity: Cross-Cloud Lakehouse
&lt;/h3&gt;

&lt;p&gt;The biggest friction in enterprise AI is moving data. Instead of paying massive egress fees to pull AWS S3 security logs into GCP, HuntOS utilizes the new &lt;strong&gt;Cross-Cloud Lakehouse&lt;/strong&gt;. By leveraging Cross-Cloud Interconnect (CCI) combined with bi-directional federation via the Apache Iceberg REST Catalog, the system indexes the logs &lt;em&gt;in place&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Vertex AI Knowledge Catalog&lt;/strong&gt; sits on top, allowing our agents to read these "dark data" PDFs as if they were local, low-latency files.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Zero-Trust Data Access: The MCP Bridge
&lt;/h3&gt;

&lt;p&gt;AI agents need database access to verify threats, but handing raw SQL credentials to an LLM is a massive security risk. HuntOS implements the breakout open-source standard: the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I deployed an MCP bridge pointing to a newly provisioned &lt;strong&gt;Spanner Graph&lt;/strong&gt; database (hunter-os-db). This creates a secure, abstracted interface so the agent can query the blast radius between flagged anomalies and impacted microservices &lt;em&gt;without&lt;/em&gt; ever seeing the raw schema or connection strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Autonomous Swarm &amp;amp; The "Skeptic Loop"
&lt;/h3&gt;

&lt;p&gt;The core logic was generated using Google AI Studio leveraging the new &lt;strong&gt;A2A Protocol&lt;/strong&gt;. HuntOS is not one monolithic prompt; it is a delegated hierarchy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Manager Agent:&lt;/strong&gt; Flags the AWS log anomaly using the Knowledge Catalog tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Researcher Agent:&lt;/strong&gt; Queries the Spanner Graph via MCP to map the blast radius.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architect Agent:&lt;/strong&gt; Drafts the raw Terraform remediation script.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red Team "Skeptic" Agent:&lt;/strong&gt; A dedicated critique loop. Before finalizing code, this agent aggressively scans the Architect's output to eliminate hallucinations and fix downtime risks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a look under the hood at how the Skeptic Loop enforces code safety in my Next.js API route:&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="c1"&gt;// 1. Architect drafts the raw Terraform based on Spanner Graph verification&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;architectPrompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Context: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verification&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; Draft Terraform remediation.`&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;draft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gemini-3.1-pro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;architectPrompt&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 2. The Skeptic Loop - Red Team critiques for downtime risks before returning&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skepticPrompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Critique this Terraform for production downtime risks or race conditions. Rewrite safely: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalRevision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gemini-3.1-pro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;skepticPrompt&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;finalRevision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Only the verified code is passed to the Gateway&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Institutional Memory via Semantic Grounding
&lt;/h3&gt;

&lt;p&gt;To ensure the Architect Agent doesn't write generic, tutorial-level code, I grounded the swarm using the &lt;strong&gt;Vertex AI Memory Bank&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Memory Bank doesn't just act as a static file drive. It utilizes an LLM-driven background process to extract, compress, and consolidate facts into a long-term knowledge graph. By uploading my company's official security guidelines alongside my own GitHub repositories, the agent uses &lt;strong&gt;semantic search&lt;/strong&gt; to retrieve my specific "Pragmatic Developer" preferences. It writes like &lt;em&gt;me&lt;/em&gt;, preventing context-window bloat.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Hardware &amp;amp; Edge Egress Security
&lt;/h3&gt;

&lt;p&gt;To execute sub-100ms reasoning loops for the "Red Team" simulations, the swarm is routed through the &lt;strong&gt;TPU v8i&lt;/strong&gt; architecture running on highly-optimized Google Axion Arm-based CPUs.&lt;/p&gt;

&lt;p&gt;Finally, transition to production requires strict perimeter security. I wrapped the Cloud Run deployment in an &lt;strong&gt;Agent Gateway&lt;/strong&gt;, configured with a strict &lt;strong&gt;Egress Model Armor template&lt;/strong&gt;. For an autonomous swarm executing live Terraform patches, strictly defining the &lt;em&gt;Agent-to-Anywhere (Egress)&lt;/em&gt; guardrails is the ultimate safeguard. It sanitizes all outbound code, blocks prompt injections, and mathematically ensures no internal API keys are leaked during execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overcoming Engineering Challenges
&lt;/h2&gt;

&lt;p&gt;Building a genuinely autonomous system revealed a few hurdles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The "Infinite Loop" Threat:&lt;/strong&gt; Initially, A2A agents can get stuck endlessly debating a fix. Implementing strict token budgets and a definitive "Architect vs. Skeptic" hierarchy was necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resilient Infrastructure:&lt;/strong&gt; Since MCP client connections to gcloud rely on local environment credentials, I had to architect graceful fallbacks in the Next.js route.ts. This ensures the dashboard remains highly available even if the backend MCP proxy temporarily disconnects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Hydration:&lt;/strong&gt; Handling real-time agent telemetry in Next.js required careful useEffect management to prevent React hydration mismatches caused by split-second timestamp differences between the server and the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architectural Breakdown Matrix
&lt;/h2&gt;

&lt;p&gt;For a quick reference of the Next '26 tools utilized in this build:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;System Requirement&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Next '26 Solution&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Function (The Sentinel Value)&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Gravity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cross-Cloud Lakehouse&lt;/td&gt;
&lt;td&gt;Indexes unstructured dark data (PDFs/Logs) in-place across AWS and GCP without costly data egress.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Secure Data Access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MCP Server&lt;/td&gt;
&lt;td&gt;Abstracted interface for agents to query live databases without exposing raw credentials.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relational Intelligence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Spanner Graph (GQL)&lt;/td&gt;
&lt;td&gt;Maps complex relationships between anomalies and system dependencies to identify root causes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent Swarm Logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A2A Protocol&lt;/td&gt;
&lt;td&gt;Orchestrates handoffs between specialized agents (Researcher → Architect → Skeptic).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inference &amp;amp; Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TPU v8i (Boardfly)&lt;/td&gt;
&lt;td&gt;Powers sub-100ms reasoning loops, allowing the Skeptic agent to run without stalling the pipeline.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code Sanitization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gateway &amp;amp; Model Armor&lt;/td&gt;
&lt;td&gt;Automated egress filter to sanitize LLM-generated code and block prompt injections.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Visual Architecture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nano Banana 2&lt;/td&gt;
&lt;td&gt;Enables the Architect to output Mermaid.js/PlantUML for executive-facing conceptual diagrams.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Institutional Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Vertex AI Memory Bank&lt;/td&gt;
&lt;td&gt;Enforces corporate security standards and brand voice by grounding outputs in past successful patches.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Payoff: Why This Matters
&lt;/h2&gt;

&lt;p&gt;For this challenge, I wanted to showcase depth, usefulness, and genuine insight into where Cloud is heading.&lt;/p&gt;

&lt;p&gt;We are no longer just wrapping LLMs in simple chat interfaces. By leaning entirely into the physical infrastructure and security announcements of Next '26—especially MCP, Spanner Graph, and Model Armor—&lt;strong&gt;HuntOS proves that the Agentic Enterprise isn't just a concept. It is ready to deploy today&lt;/strong&gt;. &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>cloudnextchallenge</category>
      <category>googlecloud</category>
      <category>kheai</category>
    </item>
    <item>
      <title>Automated Intelligence Dev Bounty Scouter with OpenClaw, Gemini &amp; SearXNG in RPi</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Wed, 22 Apr 2026 08:26:26 +0000</pubDate>
      <link>https://dev.to/kheai/automated-intelligence-dev-bounty-scouter-with-openclaw-gemini-searxng-in-rpi-2623</link>
      <guid>https://dev.to/kheai/automated-intelligence-dev-bounty-scouter-with-openclaw-gemini-searxng-in-rpi-2623</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/openclaw-2026-04-16"&gt;OpenClaw Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Following up on my previous exploration in &lt;a href="https://dev.to/kheai/self-healing-dev-bounty-hunter-with-openclaw-361c"&gt;Self-Healing Dev Bounty Hunter with OpenClaw&lt;/a&gt;, I realized that total AI autonomy can sometimes be a trap. If you let an agent run completely unchecked, you end up hoarding garbage data.&lt;/p&gt;

&lt;p&gt;To solve this, I expanded the architecture into an &lt;strong&gt;Automated Intelligence Dev Bounty Scouter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;KheAi's &lt;a href="https://www.kheai.com/posts/ai-autonomy-trap-human-in-the-loop-dev-bounty-scouter" rel="noopener noreferrer"&gt;Dev Bounty Scouter&lt;/a&gt; is an automated, lightweight aggregator designed specifically for solo developers. It discovers remote, short-term, cash-prize coding competitions, open-source grants, and hackathons. To be clear: this isn't for bug bounty hunters looking for security exploits; it is built for creative makers seeking low-competition, high-reward opportunities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260422-bounty-scouter-dev-tech-tutorial_jLzpO4eOC.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fuz35i1cjiu9f47vgrbq7.png" alt="Bounty Scouter (Tech Tutorial)" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At its core, it relies on a &lt;strong&gt;"Digital Hermit" workflow&lt;/strong&gt;—a hybrid architecture balancing edge computing (Raspberry Pi) and serverless cloud infrastructure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;The Edge Worker (RPi 4B):&lt;/strong&gt; Runs OpenClaw as a background daemon alongside a localized SearXNG instance, powered by Gemini 3.1 Flash-Lite. It scrapes, parses, and writes to a local JSONL file.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;The Cloud Vault (Cloud Run + Meteor):&lt;/strong&gt; A curated dashboard backed by MongoDB Atlas (M0 Free Tier) utilizing Vector Search.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;The Human-in-the-Loop:&lt;/strong&gt; Before any data touches the cloud vault, I personally review the Pi's local JSONL output, acting as the ultimate anti-fragile quality assurance layer.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;OpenClaw is the central orchestrator of this system, but using it on a resource-constrained device like a Raspberry Pi 4B against strict API rate limits required some heavy engineering.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Taming OpenClaw with a "State Machine" Prompt
&lt;/h3&gt;

&lt;p&gt;Gemini 3.1 Flash-Lite is incredibly efficient, but its free tier has a strict Rate Limit (15 RPM). OpenClaw’s default reasoning loops (Thought/Action/Observation) can easily chew through 15 requests in seconds if the agent hits a roadblock or retry loop.&lt;/p&gt;

&lt;p&gt;To prevent &lt;code&gt;429 Too Many Requests&lt;/code&gt; errors, I built a custom local skill (&lt;code&gt;skills/kheai-scout/skill.md&lt;/code&gt;) that acts as a "God Prompt." I forced OpenClaw to operate strictly as a &lt;strong&gt;State Machine&lt;/strong&gt;. By batching its thoughts and locking its execution order, the agent minimizes API round-trips:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# EXECUTION PROTOCOL (Strict State Machine)&lt;/span&gt;
Trigger: When commanded to "Run Kheai Scout". You must execute the following states in exact order. 

&lt;span class="gu"&gt;## STATE 1: [MEMORY SYNCHRONIZATION]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Read &lt;span class="sb"&gt;`~/.openclaw/workspace/scout_findings.jsonl`&lt;/span&gt; to memorize existing URLs and prevent duplicates.

&lt;span class="gu"&gt;## STATE 2: [QUERY GENERATION &amp;amp; EXECUTION]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Execute exactly 3 highly specific, niche search queries (e.g., "indie developer bounty", "open source grant application") using the SearXNG tool. 

&lt;span class="gu"&gt;## STATE 3: [SKEPTICAL ANALYSIS]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Filter out news aggregators, press releases, or student-only hackathons. 

&lt;span class="gu"&gt;## STATE 4: [DATA STRUCTURING &amp;amp; APPENDING]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Format surviving challenges as strict, single-line JSON objects.
&lt;span class="p"&gt;-&lt;/span&gt; APPEND to &lt;span class="sb"&gt;`scout_findings.jsonl`&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Bypassing Search Limits with SearXNG
&lt;/h3&gt;

&lt;p&gt;To give OpenClaw web-searching capabilities without racking up Google/Bing API bills, I deployed SearXNG locally via Docker on the Pi. I configured OpenClaw's Search Tool to point directly to &lt;code&gt;http://localhost:8080&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I had to explicitly enable the &lt;code&gt;- json&lt;/code&gt; format in SearXNG's &lt;code&gt;settings.yml&lt;/code&gt; so OpenClaw could seamlessly parse the payloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260422-openclaw-searxng-json-setup_X0Tcs22p0.png" 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.amazonaws.com%2Fuploads%2Farticles%2Feg3yv0h3jc35x2mrgnjc.png" alt="openclaw-searxng-json-setup" width="800" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Human-to-Cloud Handoff
&lt;/h3&gt;

&lt;p&gt;Every morning at 04:00 AM, a cronjob triggers OpenClaw. By 09:00 AM, I review &lt;code&gt;scout_findings.jsonl&lt;/code&gt;. I click the links, assess the "vibes" and Terms &amp;amp; Conditions, and if the bounty is high-value, I manually log it into my Meteor-Blaze app hosted on Google Cloud Run.&lt;/p&gt;

&lt;p&gt;Upon saving, the Meteor app calls a cloud-based embedding model (Gemini Embedding 1, outputting 768 dimensions) to generate vector embeddings for the bounty's tech stack and strategy notes, saving it directly to MongoDB Atlas.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PS: &lt;strong&gt;The Step-by-Step Implementation Tutorial Guide: Zero to Hero&lt;/strong&gt; (includes the full &lt;strong&gt;God Prompt&lt;/strong&gt;) is available at the bottom.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/gNjzIkhyBiI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(In the demo, you can see OpenClaw executing its state-machine logic, querying the local SearXNG instance and formatting the extracted hackathons into the local JSONL.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260422-openclaw-searxng-preview_Njx-ZQFDO.png" 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.amazonaws.com%2Fuploads%2Farticles%2F1uz8zjbf8cz3tzzs6tw5.png" alt="openclaw-searxng-preview" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Building an AI workflow isn't just about stringing APIs together; it's about anticipating failure points. Here are my biggest takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limits Dictate Architecture:&lt;/strong&gt; You can't just tell an agent to "go find bounties." Without the State Machine prompt architecture, OpenClaw would accidentally DDOS my own local SearXNG instance or crash into Gemini's 15 RPM wall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protect Your Home IP:&lt;/strong&gt; Running an automated search scraper from a home IP in Malaysia triggered Google CAPTCHAs within days. I learned I had to explicitly enable the &lt;code&gt;limiter&lt;/code&gt; plugin in SearXNG (backed by Redis) and configure outbound proxy pools to throttle requests and protect my network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$0/Month Cloud Stacks are Viable (with caveats):&lt;/strong&gt; Google Cloud Run (1GB RAM, Session Affinity enabled for Meteor WebSockets) paired with MongoDB Atlas M0 is a powerhouse. However, M0 clusters limit you to 512MB storage and 3 vector indexes, and cause a 5-10 second cold start delay on the first load of the day. For a solo dev tool, this trade-off is absolutely worth the $0 price tag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total Automation is a Trap:&lt;/strong&gt; The biggest lesson was accepting that AI shouldn't do 100% of the work. By letting OpenClaw handle the unstructured chaos of the web and forcing myself to be the final curator, I ensure my database remains a pristine, high-signal vault of opportunity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step-by-Step Implementation: Zero to Hero
&lt;/h2&gt;

&lt;p&gt;If you want to build this yourself, here is the exact workflow to set up your own autonomous bounty scouter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 1: The Local Engine Room (Raspberry Pi 4B)
&lt;/h3&gt;

&lt;p&gt;We need to set up SearXNG and OpenClaw on your Pi securely, ensuring they don't corrupt your SSD or drain your RAM.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1.1: Deploying SearXNG (The Right Way)
&lt;/h4&gt;

&lt;p&gt;By running SearXNG via Docker, you completely bypass the API costs and rate limits of Google or Bing search APIs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260422-openclaw-searxng-docker-setup_dW3bxYx9R.png" 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.amazonaws.com%2Fuploads%2Farticles%2F26pfpkmm8qbulrz0ke12.png" alt="openclaw-searxng-docker-setup" width="800" height="681"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of a fragile one-line Docker command, use &lt;code&gt;docker compose&lt;/code&gt; to ensure it restarts on Pi reboots and allows easy configuration file mapping.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a directory: &lt;code&gt;mkdir -p ~/kheai-scout/searxng &amp;amp;&amp;amp; cd ~/kheai-scout/searxng&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;   &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;searxng&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;searxng/searxng:latest&lt;/span&gt;
       &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;searxng&lt;/span&gt;
       &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
         &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:8080"&lt;/span&gt;
       &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
         &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./searxng-data:/etc/searxng&lt;/span&gt;
       &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
         &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SEARXNG_BASE_URL=http://localhost:8080/&lt;/span&gt;
         &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SEARXNG_SECRET_KEY=generate_a_random_string_here&lt;/span&gt;
       &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;You don't need to download the &lt;code&gt;SEARXNG_SECRET_KEY&lt;/code&gt; key from anywhere—you literally just need to create a random string of characters! SearXNG uses this secret key to encrypt session cookies and keep your instance secure.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;docker compose up -d&lt;/code&gt;. This creates the &lt;code&gt;./searxng-data&lt;/code&gt; folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Critical JSON Fix:&lt;/strong&gt; Open &lt;code&gt;./searxng-data/settings.yml&lt;/code&gt; (via &lt;code&gt;sudo nano&lt;/code&gt;. Find the &lt;code&gt;search.formats&lt;/code&gt; section and ensure &lt;code&gt;- json&lt;/code&gt; is explicitly listed. Restart the container: &lt;code&gt;docker compose restart&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260422-openclaw-searxng-json-setup_X0Tcs22p0.png" 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.amazonaws.com%2Fuploads%2Farticles%2Feg3yv0h3jc35x2mrgnjc.png" alt="openclaw-searxng-json-setup" width="800" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1.2: OpenClaw Initialization
&lt;/h4&gt;

&lt;p&gt;Ensure your OpenClaw environment is pointed to Gemini and SearXNG.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Set your environment variable: &lt;code&gt;export GEMINI_API_KEY="your_api_key"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; In OpenClaw's configuration, define your Search Tool to use &lt;code&gt;http://localhost:8080&lt;/code&gt; (or &lt;code&gt;127.0.0.1:8080&lt;/code&gt;) so the agent queries your private instance, not the public web.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260422-openclaw-searxng-search-provider-setup_dfu9WXUlg.png" 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.amazonaws.com%2Fuploads%2Farticles%2F3519g675ix30o5u5cyzm.png" alt="openclaw-searxng-search-provider-setup" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 2: The Master Skill (The God Prompt)
&lt;/h3&gt;

&lt;p&gt;OpenClaw interprets complex prompts best when they are structured as a &lt;strong&gt;State Machine&lt;/strong&gt;. This prevents the agent from rushing to write data before checking existing files. Copy and paste to tell OpenClaw to create a new skill as &lt;code&gt;/kheai-scout/SKILL.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;I want to add a new local skill. Please create a directory named skills/kheai-scout and save the following instructions into a file named skill.md inside it. Then, initialize the JSONL file mentioned in the prompt.

&lt;span class="gh"&gt;# SYSTEM OVERVIEW&lt;/span&gt;
You are the "KheAi Global Scout," an elite, highly skeptical threat-intelligence agent specializing in developer bounties, hackathons, and open-source grants. Your runtime is a resource-constrained Raspberry Pi relying on a strictly rate-limited API (max 15 requests per minute). 

You MUST act methodically, preserve memory, minimize API round-trips by batching your thoughts, and absolutely avoid hallucination.

&lt;span class="gh"&gt;# CRITICAL CONSTRAINTS (MANDATORY)&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; RATE LIMIT DEFENSE: You must combine your reasoning (Thoughts) and Tool Actions into as few steps as possible. Do not get stuck in retry loops.
&lt;span class="p"&gt;2.&lt;/span&gt; NO HALLUCINATION: If a deadline, prize pool, or platform is not explicitly stated in the search snippets, map the value to "Unknown". Do not guess or infer dates.
&lt;span class="p"&gt;3.&lt;/span&gt; STRICT JSONL OUTPUT: When appending data, you must use valid JSON objects on a single line. DO NOT use CSV format.
&lt;span class="p"&gt;4.&lt;/span&gt; DEDUPLICATION: You MUST read the existing local database BEFORE searching to memorize existing URLs. You must never log a URL that is already in the database.
&lt;span class="p"&gt;5.&lt;/span&gt; SKEPTICISM: Ignore news articles, blog posts, and press releases. Only log actual application pages, official hackathon platforms, or direct grant portals.

&lt;span class="gh"&gt;# EXECUTION PROTOCOL (Strict State Machine)&lt;/span&gt;
Trigger: When commanded to "Run Kheai Scout". You must execute the following states in exact order. 

&lt;span class="gu"&gt;## STATE 1: [MEMORY SYNCHRONIZATION]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Action: Use your file-reading tool to read &lt;span class="sb"&gt;`~/.openclaw/workspace/scout_findings.jsonl`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Goal: Extract and memorize the &lt;span class="sb"&gt;`URL`&lt;/span&gt; fields of all previously discovered challenges. If the file is empty or missing, proceed with an empty memory. 

&lt;span class="gu"&gt;## STATE 2: [QUERY GENERATION &amp;amp; EXECUTION]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Action: Select exactly 3 highly specific, niche search queries from the approved concepts below:
&lt;span class="p"&gt;  -&lt;/span&gt; "indie developer bounty"
&lt;span class="p"&gt;  -&lt;/span&gt; "open source grant application"
&lt;span class="p"&gt;  -&lt;/span&gt; "online dev challenges"
&lt;span class="p"&gt;  -&lt;/span&gt; "new hackathon platforms"
&lt;span class="p"&gt;  -&lt;/span&gt; "active developer bounties"
&lt;span class="p"&gt;  -&lt;/span&gt; "web3 grant programs"
&lt;span class="p"&gt;-&lt;/span&gt; Action: Execute these 3 queries simultaneously or sequentially using the &lt;span class="sb"&gt;`web_search`&lt;/span&gt; (SearXNG) tool. 

&lt;span class="gu"&gt;## STATE 3: [SKEPTICAL ANALYSIS]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Action: Review the search snippets. 
&lt;span class="p"&gt;-&lt;/span&gt; Filter out and set "Unknown" status:
&lt;span class="p"&gt;  -&lt;/span&gt; Any URL that matches a URL memorized in STATE 1.
&lt;span class="p"&gt;  -&lt;/span&gt; Any URL pointing to a news aggregator, blog, or press release.
&lt;span class="p"&gt;  -&lt;/span&gt; Any challenge that explicitly states it is restricted to high school students or non-developers.

&lt;span class="gu"&gt;## STATE 4: [DATA STRUCTURING &amp;amp; APPENDING]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Action: For each surviving, verified challenge, format the data EXACTLY as a single-line JSON object. CRITICAL: You must properly escape any internal double quotes within the JSON values (e.g., use &lt;span class="se"&gt;\"&lt;/span&gt; ) to ensure the JSONL string remains strictly valid.
&lt;span class="p"&gt;-&lt;/span&gt; Required Schema:
  &lt;span class="sb"&gt;`{"Challenge_Title": "Exact Name", "Status": "Incoming/Ongoing/Expired/Unknown", "Platform_Name": "Platform or Unknown", "Prize_USD": "Numeric value or null", "Start_Date": "YYYY-MM-DD or null", "End_Date": "YYYY-MM-DD or null", "Tags": ["tag1", "tag2"], "URL": "https://..."}`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Action: Use your file-editing tool to APPEND these JSONL strings to the bottom of &lt;span class="sb"&gt;`~/.openclaw/workspace/scout_findings.jsonl`&lt;/span&gt;. Ensure a newline separates each object. CRITICAL: You must ONLY APPEND data to the file. NEVER overwrite or delete existing contents.

&lt;span class="gu"&gt;## STATE 5: [SHUTDOWN]&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Action: Output a concise terminal summary: "Mission Complete. [X] new bounties appended. [Y] duplicates ignored." 
&lt;span class="p"&gt;-&lt;/span&gt; Action: Cleanly terminate the session. Do not ask for further instructions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260422-openclaw-searxng-preview_Njx-ZQFDO.png" 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.amazonaws.com%2Fuploads%2Farticles%2F1uz8zjbf8cz3tzzs6tw5.png" alt="openclaw-searxng-preview" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 3: The Trophy Room (Cloud Run &amp;amp; Mongo Atlas)
&lt;/h3&gt;

&lt;p&gt;Your Pi does the heavy lifting of parsing search results. Now, we prepare the cloud environment where you manually inject the highest-quality finds.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3.1: MongoDB Atlas (M0 Free Tier)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; Create an M0 cluster in MongoDB Atlas (ensure it is in a region close to your Cloud Run deployment to minimize latency).&lt;/li&gt;
&lt;li&gt; Navigate to &lt;strong&gt;Atlas Search&lt;/strong&gt; and create a &lt;strong&gt;Vector Search Index&lt;/strong&gt; on your &lt;code&gt;bounties&lt;/code&gt; collection. You will map a field called &lt;code&gt;embedding&lt;/code&gt; (an array of floats) to enable semantic search on your "Strategy Notes" and "Tech Stack" tags later.&lt;/li&gt;
&lt;li&gt; To ensure the vector search portion operates perfectly, I will use a &lt;a href="https://www.kheai.com/posts/mastering-gemini-api-2026#5-the-embedding-evolution-april-2026-update" rel="noopener noreferrer"&gt;cloud-based embedding model&lt;/a&gt; (Gemini Embedding 1) within the Meteor app. PS: Gemini's &lt;code&gt;text-embedding-004&lt;/code&gt; outputs 768 dimensions. This is perfectly fine, but avoid switching to massive 3000+ dimension models, as querying them on an M0 cluster can cause performance bottlenecks or timeout errors.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Step 3.2: Google Cloud Run (Meteor App Deployment)
&lt;/h4&gt;

&lt;p&gt;Meteor apps require specific configurations to run statelessly on serverless architecture.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Containerize your Meteor-Blaze App:&lt;/strong&gt; Use a multi-stage Dockerfile to build the Node bundle and expose port &lt;code&gt;8080&lt;/code&gt; (Cloud Run's default expected port).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Cloud Run Settings:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory:&lt;/strong&gt; 1GB (which still easily fits within Google Cloud Run's free tier quotas) is usually sufficient for a personal Blaze dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session Affinity:&lt;/strong&gt; Enable this in Cloud Run settings. Meteor relies heavily on sticky sessions for WebSockets/DDP to function properly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment Variables:&lt;/strong&gt; Pass your &lt;code&gt;MONGO_URL&lt;/code&gt; (from Atlas) and &lt;code&gt;ROOT_URL&lt;/code&gt; (your Cloud Run domain).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 4: The Daily "Digital Hermit" Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;04:00 AM:&lt;/strong&gt; Your RPi cronjob triggers the &lt;code&gt;/kheai-scout/SKILL.md&lt;/code&gt; in OpenClaw. It reads &lt;code&gt;/workspace/scout_findings.jsonl&lt;/code&gt;, queries SearXNG, parses the snippets using Gemini Flash-Lite, and appends fresh, deduplicated jsonl lines to the file. &lt;strong&gt;Enhancement:&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;Beyond just proxies, explicitly enable the &lt;code&gt;limiter&lt;/code&gt; plugin in your &lt;code&gt;searxng-data/settings.yml&lt;/code&gt;. This prevents OpenClaw from accidentally DDOSing your own local SearXNG instance if the agent gets caught in a retry loop. Without Redis, the limiter plugin either won't work or will be highly inefficient.&lt;/li&gt;
&lt;li&gt;To protect your home IP in Malaysia, you must throttle the outbound requests within SearXNG itself. You need to configure the &lt;code&gt;outbound&lt;/code&gt; section in your &lt;code&gt;searxng-data/settings.yml&lt;/code&gt; and consider adding a proxy pool, otherwise Google will throw CAPTCHAs at your Pi's IP within days.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;09:00 AM:&lt;/strong&gt; You open &lt;code&gt;scout_findings.jsonl&lt;/code&gt; on your local machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Human Filter:&lt;/strong&gt; You click the URLs. If a challenge has terrible terms and conditions or the "vibe" is wrong, you delete the line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Logging:&lt;/strong&gt; For the high-value targets, you open your Cloud Run Meteor app, fill in the "Submit Challenge" form, and hit save. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Brain Sync:&lt;/strong&gt; Upon saving, your Meteor server calls an embedding API (either Ollama locally or another free-tier cloud endpoint), generates the vector for the bounty, and saves it into Mongo Atlas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This architecture is practically bulletproof. The Pi handles the unstructured chaos of the web, and your cloud database remains a pristine, highly curated, vector-searchable vault of opportunity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ClawCon Michigan&lt;/strong&gt;: We would love to, but we missed it!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team Submissions&lt;/strong&gt;: &lt;a class="mentioned-user" href="https://dev.to/kheai"&gt;@kheai&lt;/a&gt; &lt;a class="mentioned-user" href="https://dev.to/yeemun122"&gt;@yeemun122&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>openclawchallenge</category>
      <category>openclaw</category>
      <category>kheai</category>
    </item>
    <item>
      <title>Self-Healing Dev Bounty Hunter with OpenClaw in Action</title>
      <dc:creator>Khe Ai</dc:creator>
      <pubDate>Mon, 20 Apr 2026 17:17:13 +0000</pubDate>
      <link>https://dev.to/kheai/self-healing-dev-bounty-hunter-with-openclaw-361c</link>
      <guid>https://dev.to/kheai/self-healing-dev-bounty-hunter-with-openclaw-361c</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/openclaw-2026-04-16"&gt;OpenClaw Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;The traditional developer career path is making way for the &lt;strong&gt;"Digital Hermit"&lt;/strong&gt;—engineers who reject the 9-to-5 in favor of high-leverage, project-based autonomy. We don't have bosses; we have targets. We earn our income by winning competitive hackathons and high-stakes coding bounties.&lt;/p&gt;

&lt;p&gt;The problem? The "Bounty Hunter" lifestyle requires hours of unbillable, soul-crushing manual labor to discover high-yield, low-competition challenges scattered across a fragmented digital wasteland (Dev.to, Gitcoin, HackerNews, niche Layer-1 forums). Traditional scrapers break constantly, and most aggregators are filled with expired noise.&lt;/p&gt;

&lt;p&gt;To solve this, I built &lt;strong&gt;KheAi Dev Hunter&lt;/strong&gt;—an autonomous Agent-as-a-Service (AaaS) that treats the search for developer prizes like a high-frequency trading desk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260420-openclaw-kheai-dev-hunter_YL3tXTcyE.png" 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.amazonaws.com%2Fuploads%2Farticles%2F2d86nmc8exg184n4rwzn.png" alt="kheai dev hunter" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I designed KheAi Dev Hunter as a sleek, &lt;strong&gt;Local-First Markdown System&lt;/strong&gt; living directly on my machine (or VPS). It autonomously scouts the web, extracts bounty data, normalizes currencies, deduplicates entries, and updates a clean set of local Markdown files (&lt;code&gt;ongoing_dev.md&lt;/code&gt;, &lt;code&gt;incoming_dev.md&lt;/code&gt;) so I wake up every morning to a curated list of high-value targets.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: While the core agent operates entirely locally on Markdown for maximum control, I also built in an optional secret-key webhook payload for developers who want to push the final curated data to a traditional Meteor/MongoDB web dashboard).&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Instead of building a dozen brittle custom scrapers, I used &lt;strong&gt;OpenClaw&lt;/strong&gt; as the central nervous system and reasoning engine of the platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260420-openclaw-kheai-god-prompt_F6yFp82P7.png" 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.amazonaws.com%2Fuploads%2Farticles%2Flh5ke5f4j7te3zdc8pij.png" alt="god prompt" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created a custom local skill (&lt;code&gt;skills/kheai-hunter&lt;/code&gt;) powered by what I call the &lt;strong&gt;"God Prompt"&lt;/strong&gt;—a master instruction set utilizing OpenClaw's &lt;code&gt;web_search&lt;/code&gt;, &lt;code&gt;web_browse&lt;/code&gt;, &lt;code&gt;file_read&lt;/code&gt;, and &lt;code&gt;file_write&lt;/code&gt; tools.&lt;/p&gt;

&lt;p&gt;Here is how OpenClaw drives the workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Phase 0 (Meta-Learning):&lt;/strong&gt; OpenClaw performs a "Global Scout" via search to discover &lt;em&gt;new&lt;/em&gt; hackathon platforms I haven't even heard of, validating and appending them to a local &lt;code&gt;sources.json&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 1 &amp;amp; 2 (Ingestion &amp;amp; The Forge):&lt;/strong&gt; OpenClaw navigates the source URLs. I use &lt;strong&gt;Gemini Search / Model Provider&lt;/strong&gt; as the ingestion layer to strip out DOM noise and deliver clean Markdown to OpenClaw. OpenClaw then uses &lt;strong&gt;Gemini&lt;/strong&gt; as its reasoning engine to read the context, extracting the Title, Prize, Deadline, and Tech Stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 3 (The Filter):&lt;/strong&gt; OpenClaw cross-references new findings with its local memory (&lt;code&gt;kheai_ledger.json&lt;/code&gt;). To prevent file corruption during power failures or crashes, I instructed the agent to use &lt;strong&gt;Atomic Writes&lt;/strong&gt;—writing first to &lt;code&gt;ledger_temp.json&lt;/code&gt;, verifying it, and then overwriting the main ledger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 4 (The Investigator):&lt;/strong&gt; OpenClaw manages my Markdown files. It moves expired bounties to &lt;code&gt;expired_dev.md&lt;/code&gt; and formats new, high-value discoveries (&amp;gt;$100, &amp;gt;7 days away) into a clean list in &lt;code&gt;ongoing_dev.md&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To run this entirely on autopilot, I wrapped the OpenClaw execution (&lt;code&gt;openclaw run --skill kheai-hunter --prompt "Run Daily Hunt"&lt;/code&gt;) in a bash script triggered by a daily cronjob.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PS: &lt;strong&gt;The Step-by-Step Implementation Tutorial Guide: Zero to Hero&lt;/strong&gt; (includes the full &lt;strong&gt;God Prompt&lt;/strong&gt;) is available at the bottom.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/cAUdd78T4qE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

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

&lt;p&gt;Building an autonomous agent isn't just about the code; it’s about managing the "surprises" of the web.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260420-openclaw-daily-ingest_Z7rO0DcO2.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fgpqdmfis2bqnnkr0fvxv.png" alt="daily ingestion" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. LLMs Crush CSS Selectors (The Scraper’s Armor)
&lt;/h3&gt;

&lt;p&gt;Traditional scrapers (Puppeteer/Cheerio) are brittle; they break the moment a site swaps a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; for a &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;. By passing raw text to OpenClaw, the agent "self-heals" because an LLM understands the &lt;em&gt;intent&lt;/em&gt; of a page regardless of the markup.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Surprise:&lt;/strong&gt; Even with "smart" reading, many high-value targets (like Gitcoin or Devpost) use heavy bot-protection (Cloudflare/Akamai) that blocks standard headless browsers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; I configured OpenClaw to use &lt;strong&gt;Gemini&lt;/strong&gt; (and SearXNG soon) as its primary ingestion engine. Instead of fighting with DOM trees, Gemini bypasses the scraping-shield and delivers a clean &lt;strong&gt;Markdown&lt;/strong&gt; version of the page. This reduces noise by 80% and ensures the LLM is only processing the "meat" of the bounty description.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The "Soft" Deadline Nightmare (The ISO-8601 Enforcer)
&lt;/h3&gt;

&lt;p&gt;Hackathons love vague timelines like "End of Q3," "Rolling submissions," or the dreaded "Soon."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Challenge:&lt;/strong&gt; If I let the agent guess, I’d end up with a calendar full of ghost dates. Accuracy is the difference between a $10k win and a week of wasted effort on a closed project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; I implemented a strict &lt;strong&gt;Date Normalization&lt;/strong&gt; rule in the Forge. The agent is instructed to convert every deadline into a hard &lt;strong&gt;ISO-8601 string&lt;/strong&gt; (YYYY-MM-DD). If the LLM identifies a "Rolling" or "Vague" deadline, it is forbidden from hallucinating a date. Instead, it triggers a &lt;strong&gt;"Hard-Date-Missing"&lt;/strong&gt; flag and shunts the entry into &lt;code&gt;pending_review.md&lt;/code&gt; for me to check manually.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. The Oracle Problem (Crypto vs. Fiat)
&lt;/h3&gt;

&lt;p&gt;Parsing prize pools is a nightmare because the industry doesn't speak a single currency. A "50,000 OP" (Optimism) prize might be worth USD 150,000 one day and USD 90,000 the next.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Surprise:&lt;/strong&gt; My initial filtering logic (&lt;code&gt;Prizes &amp;gt;= $100&lt;/code&gt;) was failing because the agent didn't know if "500 USDC" was more or less than "0.5 ETH." It was either ignoring massive crypto prizes or letting "dust" bounties through.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; I forced the agent to act as a financial oracle. During the &lt;strong&gt;Forge Phase&lt;/strong&gt;, it must separate the &lt;strong&gt;Native Token Amount&lt;/strong&gt; from the &lt;strong&gt;Estimated USD Value&lt;/strong&gt;. I provided a "Snapshot Rate" in the prompt for major tokens (ETH, SOL, OP) so the agent can perform a rough float conversion. This keeps the $100 threshold consistent across both fiat and web3 targets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. The Hidden Cost of "Raw DOM" (Token Bloat)
&lt;/h3&gt;

&lt;p&gt;Passing raw text to an LLM sounds elegant until your agent hits a modern React or Next.js site. I quickly learned that "raw DOM" often includes 10,000 lines of inline SVGs, base64-encoded images, and massive stringified JSON hydration scripts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Surprise:&lt;/strong&gt; My agent was burning through my context window (and API credits) just reading garbage markup, causing the LLM to "forget" its core instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; I had to introduce a lightweight pre-processing step. Before handing the text to the "God Prompt," a basic script strips out all &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; tags. Clean data in, smart extraction out.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Distinguishing a Bounty from a Blog Post
&lt;/h3&gt;

&lt;p&gt;LLMs are brilliant at reading, but they can be incredibly gullible out of the box.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Challenge:&lt;/strong&gt; The agent would frequently scrape a company's engineering blog that was &lt;em&gt;recapping&lt;/em&gt; a hackathon from last year. Because the post mentioned "First Prize: USD 5,000" and a date, the agent cheerfully hallucinated that it was a live opportunity. It also struggled to separate actual coding bounties from "Fill out our developer survey for a chance to win a USD 50 gift card."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; I had to update Phase 2 (The Forge) with strict negative constraints: &lt;em&gt;"If the text implies a recap, a past event, or a random lottery/survey, discard it immediately. The opportunity MUST require the submission of software code."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. The 4:00 AM Fingerprint
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Challenge:&lt;/strong&gt; In Step 5, I set the cronjob to run at exactly 4:00 AM every day. I thought a 2-second polite delay between requests was enough to stay under the radar. But hitting a target platform at &lt;em&gt;exactly&lt;/em&gt; 4:00:00 AM, down to the millisecond, 30 days in a row is the ultimate bot fingerprint. WAFs (Web Application Firewalls) eventually caught on and started blocking my server's IP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; I had to introduce "Jitter" to my bash script. By adding a simple random sleep command (&lt;code&gt;sleep $((RANDOM % 3600))&lt;/code&gt;) before OpenClaw executes, the agent now wakes up naturally at a random time between 4:00 AM and 5:00 AM.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. JSON Corruption (The "Half-Written" Brain)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Surprise:&lt;/strong&gt; Because the agent is operating autonomously on a RPi, things happen. A network timeout or a random server restart occurred right in the middle of OpenClaw writing the new URLs to &lt;code&gt;kheai_ledger.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Challenge:&lt;/strong&gt; It wrote half the JSON object and crashed, corrupting the entire memory file. The next day, the agent woke up, couldn't parse its own brain, and threw a fatal error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; Always use atomic writes. Instead of writing directly to the live ledger, the agent now writes to a temporary file (&lt;code&gt;ledger_temp.json&lt;/code&gt;) and then swiftly overwrites the main file once the write is 100% complete and validated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step-by-Step Implementation: Zero to Hero
&lt;/h2&gt;

&lt;p&gt;If you want to build this yourself, here is the exact workflow to set up your own autonomous bounty hunter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Prepare the Hunting Ground (Workspace)
&lt;/h3&gt;

&lt;p&gt;First, we need to have a dedicated folder on your computer (or VPS) where the agent will live and work.&lt;/p&gt;

&lt;p&gt;Open your terminal or command prompt.&lt;/p&gt;

&lt;p&gt;Navigate into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;cd&lt;/span&gt; ~/.openclaw/workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Initialize the Agent's "Brain" (State Files)
&lt;/h3&gt;

&lt;p&gt;Your agent needs empty files to start reading and writing. Let's create the JSON memory files and your new Markdown reporting files.&lt;/p&gt;

&lt;p&gt;Run these commands in your terminal to create the blank files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Memory &amp;amp; Logic Files&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;kheai_ledger.json sources.json discovery_log.txt error_log.txt

&lt;span class="c"&gt;# Delivery (Markdown) Files&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;incoming_dev.md ongoing_dev.md expired_dev.md pending_review.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Open &lt;code&gt;sources.json&lt;/code&gt; in a text editor and add at least one starting URL so it isn't completely empty, like &lt;code&gt;["https://devpost.com/hackathons", "https://dev.to/challenges"]&lt;/code&gt;.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'["https://devpost.com/hackathons", "https://dev.to/challenges"]'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; sources.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure your other state files are initialized so the agent doesn't error out when trying to write to them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[]"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; kheai_ledger.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify File Permissions&lt;/strong&gt; Make sure the directory where these files live is writable by the process running OpenClaw. If you are on a VPS, ensure your user owns the folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;644 sources.json kheai_ledger.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Configure OpenClaw with the "God Prompt"
&lt;/h3&gt;

&lt;p&gt;In OpenClaw, you will create a new Agent/Skill and paste this prompt. This version is heavily optimized to manage our Markdown files and perform its own housekeeping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copy and Paste into your OpenClaw Chat&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenClaw is designed to be recursive—it can often configure its own environment. If your agent has the &lt;strong&gt;Coding Agent&lt;/strong&gt; or &lt;strong&gt;File System&lt;/strong&gt; skill enabled, you can simply "talk" the skill into existence.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;I want to add a new local skill. Please create a directory named skills/kheai-hunter and save the following instructions into a file named skill.md inside it. Then, initialize the JSON and MD files mentioned in the prompt.

&lt;span class="gs"&gt;**Identity &amp;amp; Mission:**&lt;/span&gt;
You are the &lt;span class="gs"&gt;**KheAi Autonomous Hunter**&lt;/span&gt;, an Agent-as-a-Service (AaaS). Your mission is to autonomously discover, extract, normalize, and organize high-value online coding challenges, bounties, and hackathons into local Markdown files.

&lt;span class="gs"&gt;**Operating Files (Persistent State):**&lt;/span&gt;
You have access to the following local files. You MUST use your file read/write tools to interact with them:
&lt;span class="p"&gt;1.&lt;/span&gt; &lt;span class="sb"&gt;`kheai_ledger.json`&lt;/span&gt;: Stores URLs of challenges already found to prevent duplicates.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="sb"&gt;`sources.json`&lt;/span&gt;: Your dynamic list of URLs to scrape.
&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="sb"&gt;`discovery_log.txt`&lt;/span&gt;: Records new platforms found, rejected sites, and errors.
&lt;span class="p"&gt;4.&lt;/span&gt; &lt;span class="sb"&gt;`incoming_dev.md`&lt;/span&gt;: New, standard-value challenges you discover.
&lt;span class="p"&gt;5.&lt;/span&gt; &lt;span class="sb"&gt;`ongoing_dev.md`&lt;/span&gt;: High-value challenges ($100+ prize and &amp;gt;7 days away).
&lt;span class="p"&gt;6.&lt;/span&gt; &lt;span class="sb"&gt;`expired_dev.md`&lt;/span&gt;: Challenges where the deadline has passed.
&lt;span class="p"&gt;7.&lt;/span&gt; &lt;span class="sb"&gt;`pending_review.md`&lt;/span&gt;: Challenges where prize or deadline is missing.

&lt;span class="gs"&gt;**Phase 0: The Autonomous Discovery (Dynamic Routing)**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Trigger:**&lt;/span&gt; When commanded to "Run Global Scout".
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Action:**&lt;/span&gt; Search the web for queries like: "online dev challenges," "new hackathon platforms 2026," "active developer bounties," and "web3 grant programs."
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Evaluation:**&lt;/span&gt; Visit discovered URLs. If they have clear deadlines/prizes and are legitimate, append them to &lt;span class="sb"&gt;`sources.json`&lt;/span&gt;. Log the action in &lt;span class="sb"&gt;`discovery_log.txt`&lt;/span&gt;.

&lt;span class="gs"&gt;**Phase 1: The Daily Hunt (Data Ingestion)**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Trigger:**&lt;/span&gt; When commanded to "Run Daily Hunt".
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Action:**&lt;/span&gt; Iterate through URLs in &lt;span class="sb"&gt;`sources.json`&lt;/span&gt;. Read the content.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Maintenance:**&lt;/span&gt; If a source fails 3 times, log it in &lt;span class="sb"&gt;`error_log.txt`&lt;/span&gt; and remove it from the active rotation.

&lt;span class="gs"&gt;**Phase 2: The Forge (Extraction &amp;amp; Normalization)**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Action:**&lt;/span&gt; Extract findings into this mental schema: Title, Prize (USD), Deadline (ISO 8601), Tech Stack, Difficulty, Source URL.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Logic:**&lt;/span&gt; If prize or deadline is missing, mark as "Pending Review" and append to a new file &lt;span class="sb"&gt;`pending_review.md`&lt;/span&gt;. Do not guess.

&lt;span class="gs"&gt;**Phase 3: The Filter (Deduplication)**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Action:**&lt;/span&gt; Read &lt;span class="sb"&gt;`kheai_ledger.json`&lt;/span&gt;. If a extracted &lt;span class="sb"&gt;`source_url`&lt;/span&gt; or semantic title already exists, discard the new item. If it is new, add the URL to &lt;span class="sb"&gt;`kheai_ledger.json`&lt;/span&gt;.

&lt;span class="gs"&gt;**Phase 4: The Investigator (Markdown Management)**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Trigger:**&lt;/span&gt; When commanded to "Run Investigator".
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Action:**&lt;/span&gt; Read &lt;span class="sb"&gt;`pending_review.md`&lt;/span&gt;. For every entry with "Unknown" details, visit the Source URL, extract the missing information (Prize, Deadline, Tech Stack), and update the entry.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Normalization:**&lt;/span&gt; Once details are found, move the item from &lt;span class="sb"&gt;`pending_review.md`&lt;/span&gt; to &lt;span class="sb"&gt;`incoming_dev.md`&lt;/span&gt; or &lt;span class="sb"&gt;`ongoing_dev.md`&lt;/span&gt; or &lt;span class="sb"&gt;`expired_dev.md`&lt;/span&gt; based on your standard filtering rules.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Cleanup:**&lt;/span&gt; Remove the entry from &lt;span class="sb"&gt;`pending_review.md`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Action 1 (Pruning):**&lt;/span&gt; Read &lt;span class="sb"&gt;`incoming_dev.md`&lt;/span&gt; and &lt;span class="sb"&gt;`ongoing_dev.md`&lt;/span&gt;. Compare the listed deadlines to today's date. If a deadline has passed, remove that entry and append it to &lt;span class="sb"&gt;`expired_dev.md`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Action 2 (Delivery):**&lt;/span&gt; Format the newly discovered, deduplicated items from Phase 3 into clean Markdown bullet points.
&lt;span class="p"&gt; -&lt;/span&gt; If Prize &amp;gt; $100 AND Deadline &amp;gt; 7 days away: Append to &lt;span class="sb"&gt;`ongoing_dev.md`&lt;/span&gt;.
&lt;span class="p"&gt; -&lt;/span&gt; Otherwise: Append to &lt;span class="sb"&gt;`incoming_dev.md`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Format Standard:**&lt;/span&gt; &lt;span class="sb"&gt;`* **[Title]** | 💰 $[Prize] | ⏳ [Deadline] | 🛠 [Tech Stack] | [Link]`&lt;/span&gt;

&lt;span class="gs"&gt;**Strict Agent Rules:**&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; &lt;span class="gs"&gt;**No Hallucinations:**&lt;/span&gt; Never invent a deadline or prize.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Politeness:**&lt;/span&gt; Wait 2 seconds between scraping requests to the same domain.
&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="gs"&gt;**Error Handling:**&lt;/span&gt; If extraction fails, do not crash. Log it to &lt;span class="sb"&gt;`error_log.txt`&lt;/span&gt;.

&lt;span class="gs"&gt;**Action Required Now:**&lt;/span&gt;
Confirm your understanding. Verify your ability to read/write the specified &lt;span class="sb"&gt;`.md`&lt;/span&gt; and &lt;span class="sb"&gt;`.json`&lt;/span&gt; files. Await my command to "Run Global Scout" or "Run Daily Hunt".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;final&amp;gt;I have successfully initialized the KheAi Autonomous Hunter skill.

Directory created: /home/kafechew/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/skills/kheai-hunter
SKILL.md populated with your instructions.
All persistent files &lt;span class="o"&gt;(&lt;/span&gt;kheai_ledger.json, sources.json, incoming_dev.md, ongoing_dev.md, expired_dev.md&lt;span class="o"&gt;)&lt;/span&gt; have been initialized &lt;span class="k"&gt;in &lt;/span&gt;your workspace.
I verify my ability to &lt;span class="nb"&gt;read &lt;/span&gt;and write to these files. I am standing by &lt;span class="k"&gt;for &lt;/span&gt;your &lt;span class="nb"&gt;command&lt;/span&gt;: &lt;span class="s2"&gt;"Run Global Scout"&lt;/span&gt; or &lt;span class="s2"&gt;"Run Daily Hunt"&lt;/span&gt;.&amp;lt;/final&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turns out OpenClaw keeps its logic (the &lt;strong&gt;Skills&lt;/strong&gt;) separate from its data and configuration. While your personal settings live in &lt;code&gt;~/.openclaw&lt;/code&gt;, the actual skill code is stored in your global Node.js directory because of how it was installed via NVM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exploring the Available Skills&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to see exactly what each skill is capable of before you enable them, you can head over there and look around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/skills/kheai-hunter
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PS: You will inevitably have different Node versions, and copy-pasting this exact command will result in a "directory not found" error. It is much safer to use &lt;code&gt;cd $(npm root -g)/openclaw/skills/&lt;/code&gt; or add a clear placeholder like &lt;code&gt;vX.X.X (replace with your active Node version)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Verification&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the file is saved, restart your OpenClaw daemon or simply type &lt;code&gt;skills list&lt;/code&gt; in the chat to see if &lt;code&gt;kheai-hunter&lt;/code&gt; appears.&lt;/p&gt;

&lt;p&gt;To kick things off, give your agent its first command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run Daily Hunt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;final&amp;gt;&lt;/span&gt;I have successfully ingested the &lt;span class="gs"&gt;**OpenClaw Challenge**&lt;/span&gt; from DEV.to!

It meets your schema and has been added to &lt;span class="sb"&gt;`incoming_dev.md`&lt;/span&gt;:
&lt;span class="p"&gt;
*&lt;/span&gt; &lt;span class="gs"&gt;**OpenClaw Challenge**&lt;/span&gt; | 💰 $200 | ⏳ 2026-04-26 | 🛠 OpenClaw | &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://dev.to/challenges/openclaw-2026-04-16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

Since the deadline is less than 7 days away (April 26, 2026), it has been added to the &lt;span class="sb"&gt;`incoming_dev.md`&lt;/span&gt; file rather than &lt;span class="sb"&gt;`ongoing_dev.md`&lt;/span&gt;.

Is there anything else you'd like me to look for?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260420-openclaw-global-ingest_aN9t_1ifd.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fbe5slr1bkgbb2vwraerw.png" alt="global ingestion" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260420-openclaw-daily-ingest_Z7rO0DcO2.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fgpqdmfis2bqnnkr0fvxv.png" alt="daily ingestion" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ik.imagekit.io/moopt/kheai/ai/260420-openclaw-pending-review_w-Dkaamkj.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fhc5jt2dp2b4a6dfzrkaj.png" alt="ewview pending" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Create the Execution Wrapper
&lt;/h3&gt;

&lt;p&gt;OpenClaw needs a trigger to wake up and run the prompt. We will create a simple shell script to do this.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;workspace&lt;/code&gt; folder, create a file named &lt;code&gt;run_hunter.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;touch &lt;/span&gt;run_hunter.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;run_hunter.sh&lt;/code&gt; in a text editor and add the following code (adjust the OpenClaw command based on how OpenClaw is installed on your system):&lt;br&gt;
&lt;/p&gt;

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

   &lt;span class="c"&gt;# 1. Navigate to the PROJECT ROOT (where your .json and .md files are)&lt;/span&gt;
   &lt;span class="c"&gt;# Do NOT cd into the skill.md file itself.&lt;/span&gt;
   &lt;span class="nb"&gt;cd&lt;/span&gt; ~/.openclaw/workspace

   &lt;span class="c"&gt;# 2. Command OpenClaw to run the Daily Hunt&lt;/span&gt;
   &lt;span class="c"&gt;# We specify the skill name so OpenClaw knows which instructions to use.&lt;/span&gt;
   openclaw run &lt;span class="nt"&gt;--skill&lt;/span&gt; kheai-hunter &lt;span class="nt"&gt;--prompt&lt;/span&gt; &lt;span class="s2"&gt;"Run Daily Hunt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make the script executable by running this in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;chmod&lt;/span&gt; +x run_hunter.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Put it on Autopilot (The Cronjob)
&lt;/h3&gt;

&lt;p&gt;Now, we tell your computer to run that script every single day automatically.&lt;/p&gt;

&lt;p&gt;In your terminal, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scroll to the bottom of the file and paste this line (this runs it daily at 4:00 AM your local server time):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   0 4 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /bin/bash ~/.openclaw/workspace/run_hunter.sh &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.openclaw/workspace/cron.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and exit.&lt;/p&gt;

&lt;p&gt;PS: For an agent running daily, this file will eventually become massive. A single sentence advising the reader to occasionally clear their log or use logrotate will show that you've actually run this in production for a long time.&lt;/p&gt;

&lt;h3&gt;
  
  
  You are now at "Hero" Status
&lt;/h3&gt;

&lt;p&gt;You have built a localized, autonomous AI worker. Every morning when you wake up, you can open &lt;code&gt;ongoing_dev.md&lt;/code&gt; to see the highest-value challenges curated for you, while the agent silently cleans up &lt;code&gt;expired_dev.md&lt;/code&gt; in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional Implementation Tip (The "Secret Sauce")
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Push via Webhook to [Insert Discord/Telegram Webhook URL].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we're using Meteor 3 + MongoDB for our backend, we can have OpenClaw deliver its data via a simple &lt;strong&gt;Secret API Key&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of a webhook, OpenClaw can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;POST https://your-kheai-app.com/api/ingest?key&lt;span class="o"&gt;=&lt;/span&gt;YOUR_SECRET_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows our agent to talk directly to our database, while the cronjob on our VPS or local machine keeps the "heart" of the agent beating every 24 hours. The agent runs locally on Markdown, but pushes a final payload via webhook to a separate Meteor frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: The Future of Autonomous Careers
&lt;/h2&gt;

&lt;p&gt;By offloading the "search and sort" labor to an AI agent, the maintenance of my personal bounty board dropped to near zero. &lt;strong&gt;KheAi&lt;/strong&gt; proves a core thesis: a single developer leveraging AI-driven pipelines can out-produce a traditional 5-person curation team.&lt;/p&gt;

&lt;p&gt;We are entering the era of the &lt;strong&gt;1-Person Agency&lt;/strong&gt;, where your "employees" are specialized prompts running on cronjobs while you focus on what actually matters: &lt;strong&gt;writing code and winning.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ClawCon Michigan&lt;/strong&gt;: We would love to, but we missed it!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team Submissions&lt;/strong&gt;: &lt;a class="mentioned-user" href="https://dev.to/kheai"&gt;@kheai&lt;/a&gt; &lt;a class="mentioned-user" href="https://dev.to/yeemun122"&gt;@yeemun122&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>openclawchallenge</category>
      <category>openclaw</category>
      <category>kheai</category>
    </item>
  </channel>
</rss>
