<?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: Ramyasri Gade</title>
    <description>The latest articles on DEV Community by Ramyasri Gade (@ramyasri_gade_e3a15d0d31c).</description>
    <link>https://dev.to/ramyasri_gade_e3a15d0d31c</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%2F4147261%2F056e12fe-9812-4fa0-8a98-c4f10d11ad59.png</url>
      <title>DEV Community: Ramyasri Gade</title>
      <link>https://dev.to/ramyasri_gade_e3a15d0d31c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ramyasri_gade_e3a15d0d31c"/>
    <language>en</language>
    <item>
      <title>Rendering Complex AI Reasoning States in a React Dashboard</title>
      <dc:creator>Ramyasri Gade</dc:creator>
      <pubDate>Mon, 28 Sep 2026 16:59:08 +0000</pubDate>
      <link>https://dev.to/ramyasri_gade_e3a15d0d31c/rendering-complex-ai-reasoning-states-in-a-react-dashboard-32mk</link>
      <guid>https://dev.to/ramyasri_gade_e3a15d0d31c/rendering-complex-ai-reasoning-states-in-a-react-dashboard-32mk</guid>
      <description>&lt;p&gt;AI agents are useless if human operators cannot understand what they are thinking in real time.&lt;/p&gt;

&lt;p&gt;We built a React dashboard that visualizes the agent's reasoning, memory hits, and recovery actions.&lt;/p&gt;

&lt;p&gt;The difference in operator trust was dramatic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Our first UI was a simple table of incidents.&lt;/p&gt;

&lt;p&gt;It showed &lt;strong&gt;what happened&lt;/strong&gt;, but not &lt;strong&gt;why&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Operators could not tell if the agent was using a Hindsight memory recall or running fresh LLM reasoning.&lt;/p&gt;

&lt;p&gt;Trust in the system was low — &lt;strong&gt;2 out of 10 in our internal survey&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the operator cannot see the agent's confidence, they will override it.&lt;/p&gt;

&lt;p&gt;And if they override it every time, what is the point of having an agent?&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The fix — make reasoning visible
&lt;/h2&gt;

&lt;p&gt;We built a &lt;code&gt;MemoryHitBadge&lt;/code&gt; component that shows operators the source of every resolution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ui/src/components/MemoryHitBadge.tsx&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MemoryHitBadge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MemoryHitBadgeProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;durationSeconds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isRecall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;recall&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;containerClasses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isRecall&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg-violet-50 border-violet-200&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;bg-amber-50 border-amber-200&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;titleText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isRecall&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HINDSIGHT RECALL HIT&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;FRESH REASONING&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;subtitleText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isRecall&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;durationSeconds&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;s · 0 LLM tokens · playbook from memory`&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;durationSeconds&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;s · ReAct loop · playbook retained to memory`&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;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`w-full flex items-center justify-between border rounded-lg px-4 py-3 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;containerClasses&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xs font-semibold tracking-wider"&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;titleText&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;span&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;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xs"&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;subtitleText&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;span&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;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-2.5 py-1 rounded-full text-[10px] font-mono font-bold"&lt;/span&gt;&lt;span class="p"&gt;&amp;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;confidence&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&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="si"&gt;}&lt;/span&gt;% CONF
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two colors, two meanings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purple&lt;/strong&gt; = instant recall from Hindsight memory (0 LLM tokens)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amber&lt;/strong&gt; = fresh ReAct reasoning, new playbook retained to memory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Operators instantly understand where every recommendation came from.&lt;/p&gt;

&lt;h2&gt;
  
  
  The live topology graph
&lt;/h2&gt;

&lt;p&gt;We also added a &lt;strong&gt;Live Topology&lt;/strong&gt; graph using &lt;code&gt;@xyflow/react&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It shows the full microservice architecture with real-time status.&lt;/p&gt;

&lt;p&gt;When an incident fires, the impacted services light up.&lt;/p&gt;

&lt;p&gt;This gives operators the blast radius in one glance instead of requiring them to scroll through logs.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                ┌─────────────┐
                │ AI Copilot  │
                └──────┬──────┘
                       │
        ┌──────────────┼──────────────┐
        ↓              ↓              ↓
   Memory Service   Incident      Execution
                     Engine        Engine
        ↓              ↓              ↓
     Hindsight      Database    Kubernetes
                                       ↓
                                Recovery Engine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The topology graph turns that architecture into something operators can understand visually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polling strategy — the hidden performance trap
&lt;/h2&gt;

&lt;p&gt;The dashboard polls the Backend-For-Frontend every 3 seconds.&lt;/p&gt;

&lt;p&gt;But naive polling can create unnecessary traffic and background work.&lt;/p&gt;

&lt;p&gt;We use &lt;strong&gt;TanStack Query&lt;/strong&gt; with two important settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ui/src/App.tsx&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;defaultOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;refetchInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;refetchIntervalInBackground&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="na"&gt;refetchOnWindowFocus&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="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;The important flag here is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;refetchIntervalInBackground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It pauses polling when the tab is inactive.&lt;/p&gt;

&lt;p&gt;Before this, a developer with 5 tabs open could generate roughly &lt;strong&gt;5x the polling traffic&lt;/strong&gt; against the BFF.&lt;/p&gt;

&lt;p&gt;After enabling the flag, background traffic drops to near zero when nobody is looking at the dashboard.&lt;/p&gt;

&lt;p&gt;This is a small configuration change, but it makes a noticeable difference when multiple dashboards or tabs are open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before vs after
&lt;/h2&gt;

&lt;p&gt;The following results are from our project testing:&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;Before&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;After&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard render latency&lt;/td&gt;
&lt;td&gt;2.5s&lt;/td&gt;
&lt;td&gt;150ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operator trust (internal survey)&lt;/td&gt;
&lt;td&gt;2/10&lt;/td&gt;
&lt;td&gt;8/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI pages&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Background polling traffic&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Near zero when inactive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We achieved the approximately &lt;strong&gt;150ms render latency&lt;/strong&gt; by shifting from heavy API aggregation to a &lt;strong&gt;Backend-For-Frontend (BFF)&lt;/strong&gt; architecture.&lt;/p&gt;

&lt;p&gt;The BFF handles aggregation.&lt;/p&gt;

&lt;p&gt;The UI focuses on rendering.&lt;/p&gt;

&lt;p&gt;That separation keeps the frontend simpler and reduces the amount of work required by individual UI components.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest lesson
&lt;/h2&gt;

&lt;p&gt;Complex distributed systems require simplified, highly visual UI components to establish trust with human operators.&lt;/p&gt;

&lt;p&gt;A confidence badge can communicate more quickly than a log file.&lt;/p&gt;

&lt;p&gt;A visual topology can communicate more quickly than a metrics dump.&lt;/p&gt;

&lt;p&gt;If you are building an AI agent, budget meaningful engineering time for the UI.&lt;/p&gt;

&lt;p&gt;It is not decoration.&lt;/p&gt;

&lt;p&gt;It is the interface between the agent's reasoning and the human's judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this fits with agent memory
&lt;/h2&gt;

&lt;p&gt;The point of a memory layer such as &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; is not only to store information.&lt;/p&gt;

&lt;p&gt;The operator also needs to understand when that memory was used.&lt;/p&gt;

&lt;p&gt;The UI shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether the current resolution is a recall hit or fresh reasoning&lt;/li&gt;
&lt;li&gt;The confidence score for every decision&lt;/li&gt;
&lt;li&gt;The blast radius of every incident&lt;/li&gt;
&lt;li&gt;The history of similar incidents from &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;agent memory&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without this visibility, operators can experience the agent as a black box.&lt;/p&gt;

&lt;p&gt;With it, they can understand where a recommendation came from and why the system selected it.&lt;/p&gt;

&lt;p&gt;The overall flow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incident Detected
       ↓
Agent Analysis
       ↓
┌──────────────────────┐
│ Memory Recall Match? │
└──────────┬───────────┘
           │
      ┌────┴────┐
      ↓         ↓
    Recall    Fresh
      ↓       Reasoning
      └────┬────┘
           ↓
     Decision + Confidence
           ↓
       UI Dashboard
           ↓
   Recovery / Verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dashboard makes these states visible instead of hiding them behind API calls and logs.&lt;/p&gt;

&lt;p&gt;You can explore how persistent memory works in the &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also explore the &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight GitHub repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>ui</category>
      <category>ai</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
