<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: ujja</title>
    <description>The latest articles on Forem by ujja (@ujja).</description>
    <link>https://forem.com/ujja</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png</url>
      <title>Forem: ujja</title>
      <link>https://forem.com/ujja</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ujja"/>
    <language>en</language>
    <item>
      <title>Fourbidden: A Serious AI Solution to 2+2, With Maximum Ceremony and No Resolution</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Sun, 05 Apr 2026 10:04:34 +0000</pubDate>
      <link>https://forem.com/ujja/fourbidden-a-serious-ai-solution-to-22-with-maximum-ceremony-and-no-resolution-3p1g</link>
      <guid>https://forem.com/ujja/fourbidden-a-serious-ai-solution-to-22-with-maximum-ceremony-and-no-resolution-3p1g</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aprilfools-2026"&gt;DEV April Fools Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I built &lt;strong&gt;Fourbidden&lt;/strong&gt;, a fake AI product dedicated to solving one extremely serious global problem: &lt;code&gt;2+2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The joke is that the problem could not be smaller, but the app treats it like the final summit of machine reasoning.&lt;/p&gt;

&lt;p&gt;You ask a basic addition question, and instead of getting a basic addition answer, the app starts trying to &lt;strong&gt;sum up&lt;/strong&gt; its own importance.&lt;/p&gt;

&lt;p&gt;That means you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-generated loading statements that sound suspiciously strategic&lt;/li&gt;
&lt;li&gt;circular explainers that get more philosophical and less useful over time&lt;/li&gt;
&lt;li&gt;escalating terms and conditions that keep turning arithmetic into a compliance event&lt;/li&gt;
&lt;li&gt;procedural next steps designed to preserve momentum without producing closure&lt;/li&gt;
&lt;li&gt;dashboard widgets, warnings, and theatrical system language&lt;/li&gt;
&lt;li&gt;surprise interactions like panic overlays, chaos toasts, prank label swaps, and a hidden Konami-style chaos mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The T&amp;amp;C bit became one of my favorite parts of the whole thing.&lt;/p&gt;

&lt;p&gt;The user is effectively told that before they can move closer to understanding &lt;code&gt;2+2&lt;/code&gt;, they must first acknowledge expanding legal nonsense, accept more conditions, and agree to one more procedural step. Then another. Then another.&lt;/p&gt;

&lt;p&gt;So the core gag is not just overengineering. It is &lt;strong&gt;over-addition&lt;/strong&gt;: treating the smallest possible math question like a high-risk, high-governance product flow.&lt;/p&gt;

&lt;p&gt;It is a satire of software that cannot simply give you the answer, because it is too busy building a whole process around the answer.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Live demo: &lt;a href="https://ujjavala.github.io/fourbidden/" rel="noopener noreferrer"&gt;https://ujjavala.github.io/fourbidden/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Local version: &lt;code&gt;http://localhost:3000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Main routes:

&lt;ul&gt;
&lt;li&gt;Home: &lt;code&gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;About: &lt;code&gt;/about&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Services: &lt;code&gt;/services&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/ujjavala/fourbidden" rel="noopener noreferrer"&gt;https://github.com/ujjavala/fourbidden&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Key route surface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/api/explain&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/loading&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/terms&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/steps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/loop&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/widgets&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I wanted the app to feel like a glossy software product that exists entirely to avoid resolving &lt;code&gt;2+2&lt;/code&gt; in a straightforward way.&lt;/p&gt;

&lt;p&gt;So instead of making a single punchline screen, I built a full fake workflow around the idea of “solving” the problem while constantly refusing to complete it.&lt;/p&gt;

&lt;p&gt;Tech stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next.js 14 (App Router)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React + TypeScript&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google AI (Gemini API)&lt;/strong&gt; to generate the app's overblown explanations, loading copy, legal nonsense, escalation steps, loop logic, and widget chatter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom CSS&lt;/strong&gt; for the bright cinematic UI, orbit effects, shimmer, flashes, and overly dramatic motion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lucide React&lt;/strong&gt; for icon-driven UI accents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementation choices that shape the vibe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The main joke is taking the tiniest math problem and inflating it into a full-stack event.&lt;/li&gt;
&lt;li&gt;The interface looks polished enough to imply a seed round and a brand strategy deck.&lt;/li&gt;
&lt;li&gt;The T&amp;amp;C flow is central to the bit: the user keeps having to consent to more nonsense before progress can allegedly continue.&lt;/li&gt;
&lt;li&gt;The text stays intentionally circular and jargon-heavy so the app never gives the satisfaction of a clean conclusion.&lt;/li&gt;
&lt;li&gt;The click surprises add a second layer of April Fools chaos on top of the main workflow.&lt;/li&gt;
&lt;li&gt;There is a static fallback path so the absurdity still works even when live AI calls are unavailable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Leveraged Google AI
&lt;/h2&gt;

&lt;p&gt;Gemini is the narrative engine for the whole product illusion.&lt;/p&gt;

&lt;p&gt;I did not use it as a single chatbot response. I split the experience into multiple AI-backed roles so each part of the fake platform has its own voice and function.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/api/explain&lt;/code&gt;: produces long-form ceremonial non-answers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/loading&lt;/code&gt;: turns waiting into executive messaging&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/terms&lt;/code&gt;: creates useless compliance clauses and acceptance loops around &lt;code&gt;2+2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/steps&lt;/code&gt;: invents process-heavy next actions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/loop&lt;/code&gt;: explains why completion is still not operationally appropriate&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api/widgets&lt;/code&gt;: generates fake platform telemetry and side-channel noise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To keep that experience stable, I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prompt caching with a short TTL&lt;/li&gt;
&lt;li&gt;retry and backoff handling for quota and rate-limit failures&lt;/li&gt;
&lt;li&gt;local fallback generators when Gemini is unavailable&lt;/li&gt;
&lt;li&gt;client-side static mode for static hosting environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That way the joke survives whether the AI is live, rate-limited, or completely absent.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Best Google AI Usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Google AI is not just providing flavor text here. It is powering the entire illusion that a hopelessly overbuilt software stack has been assembled to “solve” a single grade-school math prompt. Every stage of that ridiculous journey gets its own AI-generated nonsense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Ode to Larry Masinter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This app is proudly unnecessary. It manufactures protocol, ceremony, terms, gates, and pseudo-serious internet behavior around a task that should end instantly. It feels like the kind of thing that technically works while making arithmetic worse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Community Favorite&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think the joke lands quickly: everyone understands &lt;code&gt;2+2&lt;/code&gt;, and everyone also recognizes software that delivers process instead of outcomes. Combining those two ideas made it easy to build something immediate, silly, and annoyingly plausible.&lt;/p&gt;

&lt;p&gt;If it makes people laugh and also mutter, "why does this feel plausible," then it did its job.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
      <category>gemini</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Fri, 20 Mar 2026 11:35:27 +0000</pubDate>
      <link>https://forem.com/ujja/-141o</link>
      <guid>https://forem.com/ujja/-141o</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" class="crayons-story__hidden-navigation-link"&gt;I Built EchoHR: The HR System That Doesn’t Ghost You&lt;/a&gt;
    &lt;div class="crayons-article__cover crayons-article__cover__image__feed"&gt;
      &lt;iframe src="https://www.youtube.com/embed/D1zYQVfRA8w" title="I Built EchoHR: The HR System That Doesn’t Ghost You"&gt;&lt;/iframe&gt;
    &lt;/div&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Notion MCP Challenge Submission 🧠&lt;/p&gt;

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

          &lt;a href="/ujja" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" alt="ujja profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ujja" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ujja
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ujja
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3334932" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ujja" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ujja&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 12&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" id="article-link-3334932"&gt;
          I Built EchoHR: The HR System That Doesn’t Ghost You
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/notionchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;notionchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mcp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mcp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;47&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              63&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Big drop for EchoHR 🚀
🔧 Postgres queue + worker, idempotent + HMAC webhooks, retries/backoff, metrics
✨ Cleaner UX with hero video, logo, and clearer lifecycle
⚙️ More reliable setup + Docker flow (migrate seed worker)
Check out the blog for more 👇</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Tue, 17 Mar 2026 06:08:56 +0000</pubDate>
      <link>https://forem.com/ujja/big-drop-for-echohr-postgres-queue-worker-idempotent-hmac-webhooks-retriesbackoff-387</link>
      <guid>https://forem.com/ujja/big-drop-for-echohr-postgres-queue-worker-idempotent-hmac-webhooks-retriesbackoff-387</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" class="crayons-story__hidden-navigation-link"&gt;I Built EchoHR: The HR System That Doesn’t Ghost You&lt;/a&gt;
    &lt;div class="crayons-article__cover crayons-article__cover__image__feed"&gt;
      &lt;iframe src="https://www.youtube.com/embed/D1zYQVfRA8w" title="I Built EchoHR: The HR System That Doesn’t Ghost You"&gt;&lt;/iframe&gt;
    &lt;/div&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Notion MCP Challenge Submission 🧠&lt;/p&gt;

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

          &lt;a href="/ujja" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" alt="ujja profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ujja" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ujja
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ujja
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3334932" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ujja" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ujja&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 12&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" id="article-link-3334932"&gt;
          I Built EchoHR: The HR System That Doesn’t Ghost You
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/notionchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;notionchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mcp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mcp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;47&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              63&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built EchoHR: The HR System That Doesn’t Ghost You</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Thu, 12 Mar 2026 02:26:38 +0000</pubDate>
      <link>https://forem.com/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i</link>
      <guid>https://forem.com/ujja/i-built-echohr-the-hr-system-that-doesnt-ghost-you-1c2i</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/notion-2026-03-04"&gt;Notion MCP Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Rejections hurt. But ghosting hurts even more.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;EchoHR is a &lt;strong&gt;Notion-native employee lifecycle system&lt;/strong&gt; that ensures candidates and employees always receive timely updates, feedback, and visibility across their entire journey.&lt;/p&gt;

&lt;p&gt;The goal is simple:&lt;/p&gt;

&lt;p&gt;No candidate or employee should ever feel ghosted.&lt;/p&gt;

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

&lt;p&gt;EchoHR is a fully automated employee lifecycle management system built on top of Notion MCP.&lt;/p&gt;

&lt;p&gt;It provisions an entire HR operating system inside Notion, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;20+ interconnected lifecycle data sources
&lt;/li&gt;
&lt;li&gt;versioned workspace hubs
&lt;/li&gt;
&lt;li&gt;relations and rollups across the entire employee journey
&lt;/li&gt;
&lt;li&gt;automation playbooks
&lt;/li&gt;
&lt;li&gt;AI-ready fields for feedback and summaries
&lt;/li&gt;
&lt;li&gt;startup-scale demo datasets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system covers the complete lifecycle:&lt;/p&gt;

&lt;p&gt;Candidates → Applications → Interviews → Offers → Onboarding → Check-ins → Goals → Achievements → Performance Reviews → Compensation → Offboarding → Alumni&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%2Fr0gwcygyzkxniovd8gaa.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%2Fr0gwcygyzkxniovd8gaa.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All records are connected through Notion relations and rollups, enabling a complete view of every employee journey.&lt;/p&gt;

&lt;p&gt;To make experimentation easy for hackathons and demos, EchoHR can provision the entire workspace with one command.&lt;/p&gt;

&lt;p&gt;This instantly creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lifecycle pipelines
&lt;/li&gt;
&lt;li&gt;feedback workflows
&lt;/li&gt;
&lt;li&gt;onboarding journeys
&lt;/li&gt;
&lt;li&gt;review systems
&lt;/li&gt;
&lt;li&gt;promotion tracking
&lt;/li&gt;
&lt;li&gt;exit processes
&lt;/li&gt;
&lt;li&gt;dashboards and demo data&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt;Suggested demo flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One-command provisioning of the EchoHR workspace
&lt;/li&gt;
&lt;li&gt;Hiring pipeline with candidate progress
&lt;/li&gt;
&lt;li&gt;Automated onboarding journeys
&lt;/li&gt;
&lt;li&gt;AI-generated interview summaries
&lt;/li&gt;
&lt;li&gt;Slack notification workflows
&lt;/li&gt;
&lt;li&gt;Lifecycle dashboards and reporting&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Show us the code
&lt;/h2&gt;

&lt;p&gt;GitHub repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ujjavala/EchoHR" rel="noopener noreferrer"&gt;https://github.com/ujjavala/EchoHR&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repository includes everything needed to spin up a fully functional EchoHR workspace.&lt;/p&gt;

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

&lt;p&gt;EchoHR uses Notion MCP as the operational layer for lifecycle management.&lt;/p&gt;

&lt;p&gt;It enables AI agents, automation workflows, and integrations to operate directly on structured HR data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Notion MCP (hosted)
&lt;/h3&gt;

&lt;p&gt;Notion MCP provides the primary CRUD and schema layer for lifecycle operations.&lt;/p&gt;

&lt;p&gt;It is used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;provisioning databases
&lt;/li&gt;
&lt;li&gt;creating lifecycle records
&lt;/li&gt;
&lt;li&gt;updating candidate stages
&lt;/li&gt;
&lt;li&gt;logging check-ins
&lt;/li&gt;
&lt;li&gt;posting AI summaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;EchoHR includes a one-click workspace provisioning command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run demo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These provisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pages
&lt;/li&gt;
&lt;li&gt;data sources
&lt;/li&gt;
&lt;li&gt;relations
&lt;/li&gt;
&lt;li&gt;rollups
&lt;/li&gt;
&lt;li&gt;demo records
&lt;/li&gt;
&lt;li&gt;automation playbooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agents can then operate on the workspace through MCP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slack MCP
&lt;/h3&gt;

&lt;p&gt;Slack MCP enables human-first notifications so important updates never stall.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;candidate update reminders
&lt;/li&gt;
&lt;li&gt;onboarding alerts
&lt;/li&gt;
&lt;li&gt;offer acceptance notifications
&lt;/li&gt;
&lt;li&gt;overdue feedback pings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures recruiters and managers stay responsive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Figma MCP
&lt;/h3&gt;

&lt;p&gt;EchoHR integrates with design workflows through Figma MCP.&lt;/p&gt;

&lt;p&gt;Example automation:&lt;/p&gt;

&lt;p&gt;When a Figma frame is marked Ready for Review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A review task is created in Notion
&lt;/li&gt;
&lt;li&gt;The task links to the relevant check-in
&lt;/li&gt;
&lt;li&gt;A Slack notification is posted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This bridges the design → product → engineering workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calendar MCP Pattern
&lt;/h3&gt;

&lt;p&gt;EchoHR uses calendar MCP patterns to schedule lifecycle events.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;interview loops
&lt;/li&gt;
&lt;li&gt;onboarding meetings
&lt;/li&gt;
&lt;li&gt;post-offer check-ins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agents create tasks in Notion and schedule them via calendar integrations.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI MCP (automation server)
&lt;/h3&gt;

&lt;p&gt;EchoHR includes an automation server that processes lifecycle notes and generates structured summaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Under the Hood: MCP as an Orchestration Layer
&lt;/h3&gt;

&lt;p&gt;Beyond individual integrations, EchoHR uses MCP as a coordination layer across systems.&lt;/p&gt;

&lt;p&gt;Notion acts as the operational control plane, while automation and heavier workflows are handled via webhooks and an external automation server.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;event-driven workflows (no polling)
&lt;/li&gt;
&lt;li&gt;cross-tool orchestration (Notion + Slack + Figma + OpenAI)
&lt;/li&gt;
&lt;li&gt;real-time feedback loops (notes → AI → Notion → Slack)
&lt;/li&gt;
&lt;li&gt;scalability patterns like rate limiting, batching, and optional external storage
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to keep humans in the loop, while MCP handles coordination across the lifecycle.&lt;/p&gt;

&lt;p&gt;Example endpoint:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/webhooks/meeting-notes&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This converts raw notes into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;interview feedback summaries
&lt;/li&gt;
&lt;li&gt;candidate-safe responses
&lt;/li&gt;
&lt;li&gt;manager action items&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The summaries are written back into Notion records automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Notion Workspace Seeder
&lt;/h3&gt;

&lt;p&gt;The workspace seeder provisions the entire HR operating system.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;lifecycle databases
&lt;/li&gt;
&lt;li&gt;relations and rollups
&lt;/li&gt;
&lt;li&gt;templates
&lt;/li&gt;
&lt;li&gt;automation playbooks
&lt;/li&gt;
&lt;li&gt;demo datasets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running the setup creates a fully operational HR workspace inside Notion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation Server
&lt;/h3&gt;

&lt;p&gt;EchoHR includes a lightweight automation server that connects Notion to external systems.&lt;/p&gt;

&lt;p&gt;Endpoints include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /webhooks/notion

POST /webhooks/figma

POST /webhooks/meeting-notes

POST /summaries/interview

POST /summaries/review

POST /summaries/exit

POST /slack/notify

GET /health
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These endpoints power automated workflows across the employee lifecycle. They are triggered by Notion lifecycle events and external signals, enabling event-driven automation instead of polling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Automations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Candidate Workflow
&lt;/h3&gt;

&lt;p&gt;When a new candidate is created in Notion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An application record is automatically created
&lt;/li&gt;
&lt;li&gt;An SLA follow-up task is assigned to the recruiter&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Offer Workflow
&lt;/h3&gt;

&lt;p&gt;When an offer status becomes Accepted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An onboarding journey is created
&lt;/li&gt;
&lt;li&gt;The first three monthly check-ins are scheduled
&lt;/li&gt;
&lt;li&gt;onboarding tasks are generated&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Design Workflow
&lt;/h3&gt;

&lt;p&gt;When a Figma frame is marked Ready for Review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A review task is created in Notion
&lt;/li&gt;
&lt;li&gt;The task attaches to the relevant check-in
&lt;/li&gt;
&lt;li&gt;A Slack notification is posted&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  AI-Powered Feedback
&lt;/h2&gt;

&lt;p&gt;EchoHR integrates with OpenAI to generate summaries for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;interview feedback
&lt;/li&gt;
&lt;li&gt;performance reviews
&lt;/li&gt;
&lt;li&gt;exit interviews&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Interview notes are captured
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/webhooks/meeting-notes&lt;/code&gt; processes them
&lt;/li&gt;
&lt;li&gt;AI generates candidate-safe summaries and manager action items
&lt;/li&gt;
&lt;li&gt;The results are written back into Notion
&lt;/li&gt;
&lt;li&gt;Slack notifications ensure feedback never stalls&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;To make the system immediately usable, EchoHR seeds a realistic startup environment with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~50 employees
&lt;/li&gt;
&lt;li&gt;founders and executives
&lt;/li&gt;
&lt;li&gt;HR and people operations
&lt;/li&gt;
&lt;li&gt;managers and ICs
&lt;/li&gt;
&lt;li&gt;open roles
&lt;/li&gt;
&lt;li&gt;active hiring pipelines
&lt;/li&gt;
&lt;li&gt;onboarding journeys
&lt;/li&gt;
&lt;li&gt;performance reviews
&lt;/li&gt;
&lt;li&gt;promotions and compensation events
&lt;/li&gt;
&lt;li&gt;recognition and pulse surveys
&lt;/li&gt;
&lt;li&gt;exit processes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows dashboards and workflows to be demonstrated instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  One-Command Setup
&lt;/h2&gt;

&lt;p&gt;Run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run demo&lt;/code&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;provisions the Notion workspace
&lt;/li&gt;
&lt;li&gt;creates lifecycle databases
&lt;/li&gt;
&lt;li&gt;seeds demo records
&lt;/li&gt;
&lt;li&gt;configures relations and rollups&lt;/li&gt;
&lt;li&gt;persists install state for idempotent re-runs
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also create a fresh versioned workspace:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run demo \-- \--force-new&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Each installation creates a new workspace version, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EchoHR HQ v1
&lt;/li&gt;
&lt;li&gt;EchoHR HQ v2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes experimentation safe during hackathons.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Differentiator
&lt;/h2&gt;

&lt;p&gt;Most HR software focuses on compliance and reporting.&lt;/p&gt;

&lt;p&gt;EchoHR focuses on human experience.&lt;/p&gt;

&lt;p&gt;It introduces the concept of:&lt;/p&gt;

&lt;h2&gt;
  
  
  Zero-Ghosting Lifecycle Management
&lt;/h2&gt;

&lt;p&gt;Candidates should never wonder:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Did they forget about me?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Employees should never wonder:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Am I doing well here?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;EchoHR enforces transparency through automated lifecycle checkpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;candidate update deadlines
&lt;/li&gt;
&lt;li&gt;interview feedback reminders
&lt;/li&gt;
&lt;li&gt;onboarding check-ins
&lt;/li&gt;
&lt;li&gt;review timelines
&lt;/li&gt;
&lt;li&gt;promotion visibility
&lt;/li&gt;
&lt;li&gt;exit follow-ups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything is tracked through interconnected Notion data sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations (Current Notion Constraints)
&lt;/h2&gt;

&lt;p&gt;Some capabilities are limited by the current Notion API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Views
&lt;/h3&gt;

&lt;p&gt;The API cannot create board, timeline, or gallery views.&lt;/p&gt;

&lt;p&gt;EchoHR automatically creates a page called:&lt;/p&gt;

&lt;p&gt;Set up Views (5–10 min)&lt;/p&gt;

&lt;p&gt;This guides users through configuring dashboards manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Styling
&lt;/h3&gt;

&lt;p&gt;Notion does not support custom CSS through the API.&lt;/p&gt;

&lt;p&gt;Visual structure uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page covers
&lt;/li&gt;
&lt;li&gt;emojis
&lt;/li&gt;
&lt;li&gt;callouts
&lt;/li&gt;
&lt;li&gt;curated views&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Charts
&lt;/h3&gt;

&lt;p&gt;Notion charts depend on workspace features.&lt;/p&gt;

&lt;p&gt;If unavailable, charts can be embedded from external sources such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Sheets
&lt;/li&gt;
&lt;li&gt;Datawrapper&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Formula Updates
&lt;/h3&gt;

&lt;p&gt;Formula properties cannot currently be modified after creation through the API.&lt;/p&gt;

&lt;p&gt;They must be defined during provisioning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Hiring and employee management systems often fail at one simple thing:&lt;/p&gt;

&lt;p&gt;communication.&lt;/p&gt;

&lt;p&gt;Candidates get ghosted.&lt;br&gt;&lt;br&gt;
Employees receive little feedback.&lt;br&gt;&lt;br&gt;
Performance reviews disappear into silence.&lt;/p&gt;

&lt;p&gt;EchoHR demonstrates how Notion + MCP + AI automation can create a transparent and human-first operating system for people operations.&lt;/p&gt;

&lt;p&gt;Instead of spreadsheets and disconnected tools, teams get a single lifecycle workspace where every stage is visible and actionable.&lt;/p&gt;

&lt;p&gt;EchoHR isn’t just an HR system — it’s an example of how MCP can orchestrate tools into a cohesive, event-driven lifecycle engine.&lt;/p&gt;

&lt;p&gt;One where communication is not an afterthought, but a guaranteed outcome.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>The Enablers Who Helped Me Code Forward</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Tue, 10 Mar 2026 03:31:44 +0000</pubDate>
      <link>https://forem.com/ujja/the-enablers-who-helped-me-code-forward-cai</link>
      <guid>https://forem.com/ujja/the-enablers-who-helped-me-code-forward-cai</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/wecoded-2026"&gt;2026 WeCoded Challenge&lt;/a&gt;: Echoes of Experience&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sometimes the difference between giving up and moving forward is just one person who believes in you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I started coding when I was around nine years old.&lt;/p&gt;

&lt;p&gt;My first program was written in &lt;a href="https://en.wikipedia.org/wiki/Logo_(programming_language)" rel="noopener noreferrer"&gt;LOGO&lt;/a&gt;, where I spent hours writing tiny programs using a funny-looking triangular turtle that moved across the screen. You could tell it to move forward, turn, and draw shapes, and slowly patterns would emerge. To a kid, it felt magical. A few instructions and suddenly the computer was drawing something I had imagined.&lt;/p&gt;

&lt;p&gt;Back then I had no idea what a career in tech looked like. I just knew I loved making computers do things.&lt;/p&gt;

&lt;p&gt;One thing that made my journey different from many stories I hear today was the support I received at home. My family, especially my dad, supported my interest in computers wholeheartedly. At a time when many people still questioned whether girls should pursue technology, he never did. To him it was simple — if I enjoyed it, I should pursue it.&lt;/p&gt;

&lt;p&gt;That early encouragement made a huge difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Myth of the Solo Journey&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When people talk about careers in tech, the story is often about individual effort — perseverance, hard work, determination.&lt;/p&gt;

&lt;p&gt;And while those things matter, looking back I realise something else played an equally important role: &lt;strong&gt;enablers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Throughout my journey there were always people who gave me a small push forward at the right moment.&lt;/p&gt;

&lt;p&gt;Not huge dramatic gestures. Just small nudges that made a big difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The First Catalyst&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Early in my career I had a tech lead who noticed something about me before I fully recognised it myself.&lt;/p&gt;

&lt;p&gt;I loved &lt;strong&gt;clean code&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
I loved experimenting.&lt;br&gt;&lt;br&gt;
Hackathons excited me.&lt;/p&gt;

&lt;p&gt;Instead of letting that remain just a personal interest, he organised a &lt;strong&gt;hackathon within the team&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At the time it seemed like just a fun activity. But in reality, it gave me confidence. It validated that my curiosity and enthusiasm for building things mattered.&lt;/p&gt;

&lt;p&gt;Sometimes all someone needs is that small signal that their passion is worth investing in.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Finding My Voice&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Later in another organisation I faced a different challenge.&lt;/p&gt;

&lt;p&gt;I was technically confident, but &lt;strong&gt;public speaking terrified me&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Speaking up in meetings, presenting ideas, addressing a room full of people — those things didn't come naturally to me.&lt;/p&gt;

&lt;p&gt;An office head in that organisation noticed this and gently pushed me out of my comfort zone.&lt;/p&gt;

&lt;p&gt;Encouraging me to present.&lt;br&gt;&lt;br&gt;
Encouraging me to speak up.&lt;br&gt;&lt;br&gt;
Encouraging me to trust my voice.&lt;/p&gt;

&lt;p&gt;I still remember a very simple piece of advice he gave me.&lt;/p&gt;

&lt;p&gt;He said, &lt;em&gt;“Start small. Just say hi to people in the morning.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;His reasoning was simple. If I greeted people in the hallway or by the coffee machine, when I later saw them in a meeting room they wouldn’t feel like strangers anymore. The room would feel a little less intimidating.&lt;/p&gt;

&lt;p&gt;He also said something that stuck with me — smile. Maybe crack a small joke to ease the tension.&lt;/p&gt;

&lt;p&gt;It sounded almost too simple at the time, but it worked. Slowly those rooms full of unfamiliar faces started turning into rooms with colleagues I already knew, even if only through a quick morning hello.&lt;/p&gt;

&lt;p&gt;And little by little, speaking up didn’t feel so scary anymore.&lt;/p&gt;

&lt;p&gt;Today I speak about topics I care deeply about, especially &lt;strong&gt;identity and authentication in tech&lt;/strong&gt; — something I am incredibly passionate about.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Reality of Being Heard&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you’ve worked in tech long enough, you’ve probably seen this happen.&lt;/p&gt;

&lt;p&gt;Sometimes a woman's voice is ignored.&lt;/p&gt;

&lt;p&gt;Ideas get overlooked.&lt;br&gt;&lt;br&gt;
Comments go unheard.&lt;br&gt;&lt;br&gt;
Credit sometimes travels in unexpected directions.&lt;/p&gt;

&lt;p&gt;It happens.&lt;/p&gt;

&lt;p&gt;But another truth exists too.&lt;/p&gt;

&lt;p&gt;There are also people who &lt;strong&gt;amplify voices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;People who pause the room and say,&lt;br&gt;&lt;br&gt;
&lt;em&gt;"I think she was making a really good point."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;People who make sure ideas get the attention they deserve.&lt;/p&gt;

&lt;p&gt;Over time I’ve realised the tech industry isn't defined only by the people who silence voices.&lt;/p&gt;

&lt;p&gt;It’s also shaped by the people who make sure those voices are heard.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Recognising the Enablers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Even today in my current workplace I am fortunate to work with amazing people who create that kind of environment.&lt;/p&gt;

&lt;p&gt;Looking back, my journey was never just about learning new technologies, frameworks, or systems.&lt;/p&gt;

&lt;p&gt;It was also about recognising the people who helped me move forward.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;enablers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The mentors.&lt;br&gt;&lt;br&gt;
The leaders.&lt;br&gt;&lt;br&gt;
The colleagues.&lt;br&gt;&lt;br&gt;
The allies.&lt;/p&gt;

&lt;p&gt;The people who saw potential and helped unlock it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Paying It Forward&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The biggest lesson from my journey is this:&lt;/p&gt;

&lt;p&gt;If you’ve had enablers in your life, the best thing you can do is &lt;strong&gt;become one for someone else&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Encourage the curious junior developer.&lt;br&gt;&lt;br&gt;
Support the quiet voice in the meeting.&lt;br&gt;&lt;br&gt;
Create spaces where people can experiment and grow.&lt;/p&gt;

&lt;p&gt;Sometimes a small push can change someone’s entire trajectory.&lt;/p&gt;

&lt;p&gt;I know it did for me.&lt;/p&gt;

&lt;p&gt;And to &lt;strong&gt;all the girls who want to code but feel like they can’t&lt;/strong&gt;,&lt;br&gt;&lt;br&gt;
to &lt;strong&gt;all the women and marginalised voices who sometimes feel unheard or silenced in tech&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Look around.&lt;/p&gt;

&lt;p&gt;There are often people who quietly support you, encourage you, and believe in you — sometimes even before you believe in yourself.&lt;/p&gt;

&lt;p&gt;Find those people.&lt;/p&gt;

&lt;p&gt;Recognise them.&lt;/p&gt;

&lt;p&gt;Hold on to them.&lt;/p&gt;

&lt;p&gt;Because once you identify the &lt;strong&gt;enablers&lt;/strong&gt; in your life, you’ll realise something powerful. You were never coding alone.&lt;/p&gt;

&lt;p&gt;And if you ever feel like you don’t belong in tech, remember this:&lt;/p&gt;

&lt;p&gt;Sometimes all it takes is one enabler to change your trajectory — and someday, that enabler might be you.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>wecoded</category>
      <category>dei</category>
      <category>career</category>
    </item>
    <item>
      <title>Rethinking AI Assistants: A Privacy-First Approach with Google Gemini</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Wed, 04 Mar 2026 11:09:32 +0000</pubDate>
      <link>https://forem.com/ujja/rethinking-ai-assistants-a-privacy-first-approach-with-google-gemini-4cm7</link>
      <guid>https://forem.com/ujja/rethinking-ai-assistants-a-privacy-first-approach-with-google-gemini-4cm7</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ujja/building-a-privacy-first-mobile-speech-assistant-using-google-gemini-59pm" class="crayons-story__hidden-navigation-link"&gt;Building a Privacy-First Mobile Speech Assistant Using Google Gemini&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/ujja/building-a-privacy-first-mobile-speech-assistant-using-google-gemini-59pm" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Built with Google Gemini: Writing Challenge&lt;/p&gt;

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

          &lt;a href="/ujja" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" alt="ujja profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ujja" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ujja
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ujja
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3293845" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ujja" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ujja&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ujja/building-a-privacy-first-mobile-speech-assistant-using-google-gemini-59pm" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 28&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ujja/building-a-privacy-first-mobile-speech-assistant-using-google-gemini-59pm" id="article-link-3293845"&gt;
          Building a Privacy-First Mobile Speech Assistant Using Google Gemini
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/geminireflections"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;geminireflections&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemini"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemini&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ujja/building-a-privacy-first-mobile-speech-assistant-using-google-gemini-59pm" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;20&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ujja/building-a-privacy-first-mobile-speech-assistant-using-google-gemini-59pm#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              14&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>devchallenge</category>
      <category>geminireflections</category>
      <category>gemini</category>
      <category>llm</category>
    </item>
    <item>
      <title>CommonGround: Designing Digital Spaces for Safety, Healing, and Connection</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Wed, 04 Mar 2026 11:08:35 +0000</pubDate>
      <link>https://forem.com/ujja/commonground-designing-digital-spaces-for-safety-healing-and-connection-5gim</link>
      <guid>https://forem.com/ujja/commonground-designing-digital-spaces-for-safety-healing-and-connection-5gim</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ujja/building-safer-online-spaces-with-commonground-2746" class="crayons-story__hidden-navigation-link"&gt;Building Safer Online Spaces with CommonGround&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/ujja/building-safer-online-spaces-with-commonground-2746" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;DEV Weekend Challenge: Community&lt;/p&gt;

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

          &lt;a href="/ujja" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" alt="ujja profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ujja" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ujja
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ujja
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3295220" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ujja" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ujja&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ujja/building-safer-online-spaces-with-commonground-2746" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 28&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ujja/building-safer-online-spaces-with-commonground-2746" id="article-link-3295220"&gt;
          Building Safer Online Spaces with CommonGround
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/weekendchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;weekendchallenge&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ujja/building-safer-online-spaces-with-commonground-2746" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;11&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ujja/building-safer-online-spaces-with-commonground-2746#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>What It Really Takes to Migrate 20+ Domains and 100+ SQL Tables from .NET to GraphQL</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Wed, 04 Mar 2026 11:07:25 +0000</pubDate>
      <link>https://forem.com/ujja/what-it-really-takes-to-migrate-20-domains-and-100-sql-tables-from-net-to-graphql-3deb</link>
      <guid>https://forem.com/ujja/what-it-really-takes-to-migrate-20-domains-and-100-sql-tables-from-net-to-graphql-3deb</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ujja/how-were-surviving-20-domains-and-100-sql-tables-while-migrating-our-legacy-net-backend-to-e38" class="crayons-story__hidden-navigation-link"&gt;How We’re Surviving 20+ Domains and 100+ SQL Tables While Migrating Our Legacy .NET Backend to GraphQL&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/ujja" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" alt="ujja profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ujja" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ujja
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ujja
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3255443" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ujja" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ujja&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ujja/how-were-surviving-20-domains-and-100-sql-tables-while-migrating-our-legacy-net-backend-to-e38" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 27&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ujja/how-were-surviving-20-domains-and-100-sql-tables-while-migrating-our-legacy-net-backend-to-e38" id="article-link-3255443"&gt;
          How We’re Surviving 20+ Domains and 100+ SQL Tables While Migrating Our Legacy .NET Backend to GraphQL
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/csharp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;csharp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/typescript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;typescript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/docker"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;docker&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dotnet"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dotnet&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ujja/how-were-surviving-20-domains-and-100-sql-tables-while-migrating-our-legacy-net-backend-to-e38" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;18&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ujja/how-were-surviving-20-domains-and-100-sql-tables-while-migrating-our-legacy-net-backend-to-e38#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>csharp</category>
      <category>typescript</category>
      <category>docker</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Building Safer Online Spaces with CommonGround</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Sat, 28 Feb 2026 07:42:15 +0000</pubDate>
      <link>https://forem.com/ujja/building-safer-online-spaces-with-commonground-2746</link>
      <guid>https://forem.com/ujja/building-safer-online-spaces-with-commonground-2746</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/weekend-2026-02-28"&gt;DEV Weekend Challenge: Community&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;CommonGround is built for three interconnected communities that need safe, dignified spaces to heal and connect:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DV Survivors&lt;/strong&gt; - Individuals escaping domestic violence who need anonymous, safe spaces to share their stories and connect with others who understand their experiences. They require strict privacy protections and gentle, non-triggering interactions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;People Reintegrating After Incarceration&lt;/strong&gt; - Individuals rebuilding their lives after incarceration who need judgment-free support, community connection, and resources to successfully reintegrate into society.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community Volunteers&lt;/strong&gt; - Compassionate individuals who want to help vulnerable populations but need clear guidelines, AI-powered safety tools, and structured ways to provide support without causing harm.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This app is specifically designed for &lt;strong&gt;audiences&lt;/strong&gt; who serve these populations and need trauma-informed digital tools that maintain dignity while ensuring safety.&lt;/p&gt;

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

&lt;p&gt;CommonGround is a trauma-informed community support web application that creates safe, AI-moderated spaces for vulnerable populations to connect, share, and heal together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Features:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;🎭 Three Persona System&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safety Seeker (DV survivors with anonymity focus)&lt;/li&gt;
&lt;li&gt;Fresh Start (reintegration support with no judgment)&lt;/li&gt;
&lt;li&gt;Community Support (volunteers with guided interactions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🛡️ Trauma-Informed Onboarding&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gentle, non-invasive persona selection&lt;/li&gt;
&lt;li&gt;Goal-setting with dignity-first language&lt;/li&gt;
&lt;li&gt;Privacy controls with clear explanations&lt;/li&gt;
&lt;li&gt;No forced disclosures or triggering questions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;💬 Story Circles (AI-Moderated Group Spaces)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safe group discussions with real-time AI moderation&lt;/li&gt;
&lt;li&gt;Suggested gentle edits to maintain respectful tone&lt;/li&gt;
&lt;li&gt;Private and public circle options&lt;/li&gt;
&lt;li&gt;Story sharing with dignity-preserving prompts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🤝 CoCreate Activities&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kindness Wall&lt;/strong&gt;: Community gratitude and affirmation board&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared Story&lt;/strong&gt;: Collaborative storytelling experience&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Community Map&lt;/strong&gt;: Real Leaflet-powered map with pinned safe locations, resources, and community spaces with Google Maps integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;📍 Support Services&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Curated safe resources&lt;/li&gt;
&lt;li&gt;Location-based service finder&lt;/li&gt;
&lt;li&gt;Crisis hotlines and immediate support options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🔔 Complete Notification System&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time notification banner with swipe-to-dismiss&lt;/li&gt;
&lt;li&gt;Navigation to relevant content&lt;/li&gt;
&lt;li&gt;Non-intrusive, gentle alerts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;📊 Reflection Tools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personal progress tracking&lt;/li&gt;
&lt;li&gt;Mood journaling&lt;/li&gt;
&lt;li&gt;Safe self-reflection prompts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Design Principles:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Trauma-Safe Color Palette:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Soft Indigo (#5C6BC0) - Trust and calm&lt;/li&gt;
&lt;li&gt;Calm Teal (#4DB6AC) - Healing and growth&lt;/li&gt;
&lt;li&gt;Warm Amber (#FFB74D) - Hope and warmth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Typography:&lt;/strong&gt; Inter font family for accessibility and readability&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UX Patterns:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gentle animations with Motion (Framer Motion)&lt;/li&gt;
&lt;li&gt;Dignity-first language throughout&lt;/li&gt;
&lt;li&gt;No dark patterns or forced engagement&lt;/li&gt;
&lt;li&gt;Clear exit paths on every screen&lt;/li&gt;
&lt;li&gt;Respectful micro-interactions&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;a href="https://youtu.be/lSTpnpEe464" rel="noopener noreferrer"&gt;Video URL&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ujjavala.github.io/Commongroundapp/" rel="noopener noreferrer"&gt;Demo App URL&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ujjavala/Commongroundapp" rel="noopener noreferrer"&gt;Github URL&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;This is a fully functional web application built with Figma Make. The app includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Complete authentication flow with persona selection&lt;/li&gt;
&lt;li&gt;✅ Three-step trauma-informed onboarding&lt;/li&gt;
&lt;li&gt;✅ Full dashboard with all features accessible&lt;/li&gt;
&lt;li&gt;✅ Working Story Circles with real chat interface&lt;/li&gt;
&lt;li&gt;✅ Interactive CoCreate activities including real map functionality&lt;/li&gt;
&lt;li&gt;✅ Support services directory&lt;/li&gt;
&lt;li&gt;✅ Notification system with routing&lt;/li&gt;
&lt;li&gt;✅ Profile management&lt;/li&gt;
&lt;li&gt;✅ Responsive design for mobile and desktop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key User Flows:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Login → Select Persona → Onboarding (Welcome → Goals → Privacy) → Dashboard&lt;/li&gt;
&lt;li&gt;Dashboard → Story Circles → Join Circle → Share Story&lt;/li&gt;
&lt;li&gt;Dashboard → CoCreate → Interactive Map → Explore Safe Locations&lt;/li&gt;
&lt;li&gt;Notification Banner → Click → Navigate to relevant feature&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Key Technical Implementations:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Router Architecture:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// React Router Data Mode with protected routes&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RootLayout&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ProtectedRoute&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Welcome&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ProtectedRoute&amp;gt; }&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/home/*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OnboardingCheck&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HomeDashboard&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/OnboardingCheck&amp;gt; }&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;      &lt;span class="c1"&gt;// ... more routes&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;strong&gt;Notification System:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Swipeable notification banner with navigation&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;
  &lt;span class="nx"&gt;drag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;onDragEnd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;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;onDismiss&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Interactive Map with Leaflet:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Real map with markers, popups, and Google Maps integration&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MapContainer&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userLocation&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;zoom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TileLayer&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png&lt;/span&gt;&lt;span class="dl"&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;safeLocations&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;location&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Marker&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Popup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;googleMapsUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt; &lt;span class="nx"&gt;Directions&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Popup&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Marker&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/MapContainer&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Core Technologies:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Frontend Framework:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React 18&lt;/strong&gt; with TypeScript for type-safe component development&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Router&lt;/strong&gt; (Data Mode) for client-side routing with protected routes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vite&lt;/strong&gt; for fast development and optimized builds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Styling &amp;amp; Design:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS v4&lt;/strong&gt; for utility-first styling with custom design tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Motion (Framer Motion)&lt;/strong&gt; for gentle, trauma-informed animations&lt;/li&gt;
&lt;li&gt;Custom trauma-safe color palette defined in CSS variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Libraries:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lucide React&lt;/strong&gt; - Beautiful, accessible icons throughout the interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Leaflet&lt;/strong&gt; - Interactive community maps with real geolocation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;date-fns&lt;/strong&gt; - Date formatting for timestamps and schedules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AnimatePresence&lt;/strong&gt; - Smooth enter/exit animations for modals and notifications&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Architecture Decisions:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Trauma-Informed First&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every interaction designed to preserve dignity&lt;/li&gt;
&lt;li&gt;Gentle language and non-triggering prompts&lt;/li&gt;
&lt;li&gt;Clear exit paths and no forced engagement&lt;/li&gt;
&lt;li&gt;Privacy by default with opt-in sharing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Persona-Based Experience&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Three distinct user journeys based on needs&lt;/li&gt;
&lt;li&gt;Personalized onboarding for each persona&lt;/li&gt;
&lt;li&gt;Tailored content and features per user type&lt;/li&gt;
&lt;li&gt;Flexible navigation adapting to user context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Component-Driven Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reusable, modular components&lt;/li&gt;
&lt;li&gt;Consistent design patterns across features&lt;/li&gt;
&lt;li&gt;Easy to maintain and extend&lt;/li&gt;
&lt;li&gt;Type-safe props and state management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. State Management Strategy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local storage for authentication and onboarding state&lt;/li&gt;
&lt;li&gt;React hooks (useState, useEffect) for component state&lt;/li&gt;
&lt;li&gt;URL-based routing for navigation state&lt;/li&gt;
&lt;li&gt;Future-ready for Supabase backend integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Accessibility &amp;amp; Responsiveness&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mobile-first responsive design&lt;/li&gt;
&lt;li&gt;Semantic HTML throughout&lt;/li&gt;
&lt;li&gt;Keyboard navigation support&lt;/li&gt;
&lt;li&gt;Screen reader friendly structure&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Development Workflow:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Design System First&lt;/strong&gt; - Established trauma-safe color palette and typography&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component Library&lt;/strong&gt; - Built reusable UI components following design system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Flows&lt;/strong&gt; - Implemented complete user journeys for each persona&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Features&lt;/strong&gt; - Added real map, notifications, and dynamic content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Polish &amp;amp; Refinement&lt;/strong&gt; - Gentle animations, micro-interactions, and UX improvements&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Future Enhancements:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Supabase Integration&lt;/strong&gt; for persistent data storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time AI Moderation&lt;/strong&gt; for Story Circles using AI APIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Push Notifications&lt;/strong&gt; for mobile web experience&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progressive Web App&lt;/strong&gt; features for offline support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language Support&lt;/strong&gt; for broader accessibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics Dashboard&lt;/strong&gt; for program administrators&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Built with dignity, designed for healing, powered by community.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CommonGround represents the future of trauma-informed digital services for vulnerable populations - where technology serves humanity with respect, safety, and compassion.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Building a Privacy-First Mobile Speech Assistant Using Google Gemini</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Sat, 28 Feb 2026 05:22:47 +0000</pubDate>
      <link>https://forem.com/ujja/building-a-privacy-first-mobile-speech-assistant-using-google-gemini-59pm</link>
      <guid>https://forem.com/ujja/building-a-privacy-first-mobile-speech-assistant-using-google-gemini-59pm</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mlh-built-with-google-gemini-02-25-26"&gt;Built with Google Gemini: Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I built a privacy-first mobile speech assistant designed to support people who stutter. The app focuses on fluency analysis, speech planning, roleplay practice, and pacing guidance — while keeping architecture simple and user data controlled.&lt;/p&gt;

&lt;p&gt;But this project did not begin with Gemini.&lt;/p&gt;

&lt;p&gt;It began with a question:&lt;/p&gt;

&lt;p&gt;Can I build a fully offline, LLM-powered mobile speech assistant?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Phase 1: The Offline Mobile LLM Experiment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before Gemini entered the picture, I spent significant time exploring &lt;a href="https://dev.to/ujja/offline-ai-on-mobile-tackling-whisper-llms-and-size-roadblocks-2lb7"&gt;on-device inference for mobile&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I &lt;a href="https://dev.to/ujja/my-adventures-with-client-side-ai-models-lessons-from-trying-transformerjs-163n"&gt;experimented&lt;/a&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Quantized GGUF models&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;llama.cpp bridges in React Native&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Native C++ integrations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On-device transcription pipelines&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fully offline speech + reasoning workflows&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically, I got models running.&lt;/p&gt;

&lt;p&gt;But in practice, I encountered serious constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Model weights increased app size dramatically&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory pressure on mid-tier Android devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Latency spikes when speech recognition and LLM ran together&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complex EAS builds and JNI debugging&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Difficult JS ↔ native boundary stability&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Speech applications are highly latency-sensitive. Even a few seconds of delay breaks confidence during fluency practice.&lt;/p&gt;

&lt;p&gt;At that point, I asked the community:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/ujja/has-anyone-actually-shipped-a-free-offline-mobile-llm-3h51"&gt;Has anyone shipped a production-ready offline LLM mobile&lt;/a&gt; app without heavy compromises?&lt;/p&gt;

&lt;p&gt;The responses were honest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Yes, but you compromise heavily&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quantization reduces quality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Great for demos, harder for real UX&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose two: size, speed, or reasoning quality&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Phase 2: Hackathon Build&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After those discussions, I participated in a hackathon and built a &lt;a href="https://dev.to/ujja/i-build-a-stutter-friendly-app-in-1-day-with-elm-elixir-and-copilot-24a"&gt;web-based speech pacing assistant&lt;/a&gt; using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Elm for predictable state management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Elixir + Phoenix Channels for real-time behavior&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Local LLM inference&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rule-based fallback logic&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That project, Pacemate, focused on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Real-time speech analysis&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI-powered fluency guidance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Progress tracking&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was intentionally local-first and privacy-conscious.&lt;/p&gt;

&lt;p&gt;The reception was strong. Developers appreciated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The clarity of architecture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The hybrid fallback design&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The focus on real user experience instead of AI novelty&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That positive response made me revisit the earlier community feedback more seriously.&lt;/p&gt;

&lt;p&gt;If offline mobile LLMs introduce friction, and speech apps demand low latency and stability — maybe the right solution was not extreme offline purity.&lt;/p&gt;

&lt;p&gt;That is when I began exploring &lt;strong&gt;Google Gemini 2.5 Flash&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Phase 3: Integrating Google Gemini&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of forcing everything on-device, I redesigned the mobile architecture to be hybrid and lightweight.&lt;/p&gt;

&lt;p&gt;The current mobile stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;React Native 0.81 + Expo SDK 54&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Native speech recognition (Apple Speech Framework on iOS, Google Speech Recognizer on Android)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Google Generative AI SDK&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Structured prompt architecture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rule-based offline fallback&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no mandatory backend.&lt;/p&gt;

&lt;p&gt;The runtime flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;User speaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Native speech recognition transcribes locally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transcript is sent directly to Gemini using a user-provided API key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gemini returns structured JSON feedback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The app parses and renders categorized results.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;API keys are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;User-controlled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stored locally via AsyncStorage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Never routed through my own server&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps the AI boundary extremely thin.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How Gemini Is Used Technically&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Gemini is used as a structured reasoning engine, not a free-form chatbot.&lt;/p&gt;

&lt;p&gt;Example fluency analysis prompt:&lt;/p&gt;

&lt;p&gt;Analyze the following transcript for fluency.&lt;/p&gt;

&lt;p&gt;Return strictly formatted JSON:&lt;/p&gt;

&lt;p&gt;{&lt;/p&gt;

&lt;p&gt;"summary": "",&lt;/p&gt;

&lt;p&gt;"strengths": [],&lt;/p&gt;

&lt;p&gt;"improvementAreas": [],&lt;/p&gt;

&lt;p&gt;"rephraseSuggestions": []&lt;/p&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;Transcript:&lt;/p&gt;

&lt;p&gt;"""&lt;/p&gt;

&lt;p&gt;{userTranscript}&lt;/p&gt;

&lt;p&gt;"""&lt;/p&gt;

&lt;p&gt;Implementation safeguards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Explicit schema constraints in prompt&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deterministic key naming&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON-only instruction enforcement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Defensive TypeScript parsing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatic fallback if parsing fails&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gemini 2.5 Flash was consistent enough with structure that I eliminated the need for a backend validation service.&lt;/p&gt;

&lt;p&gt;That dramatically simplified the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Roleplay and Context Handling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For conversational practice scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Conversation history is stored locally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each turn is sent with prior context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gemini maintains continuity and supportive tone.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example message structure:&lt;/p&gt;

&lt;p&gt;[&lt;/p&gt;

&lt;p&gt;{ role: "system", content: "You are supportive and concise." },&lt;/p&gt;

&lt;p&gt;{ role: "user", content: "Hi, I’d like to order a coffee." }&lt;/p&gt;

&lt;p&gt;]&lt;/p&gt;

&lt;p&gt;The challenge was balancing realism with guidance. I constrained prompts to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Avoid overly verbose responses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain conversational authenticity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide subtle, not overwhelming, fluency feedback&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gemini handled tone surprisingly well for this sensitive use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hybrid Architecture: Cloud + Fallback&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rather than choosing cloud or offline exclusively, I implemented both.&lt;/p&gt;

&lt;p&gt;When:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Internet is available&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API key is configured&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;→ Gemini powers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Fluency analysis&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sentence rephrasing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Roleplay interactions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Offline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No API key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rate limit exceeded&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;→ Rule-based fallback activates.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Basic pacing heuristics&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Template-based conversational responses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple word substitutions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Encouragement patterns&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app never hard-fails.&lt;/p&gt;

&lt;p&gt;Graceful degradation became a core design principle.&lt;/p&gt;

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

&lt;p&gt;Conceptually, the mobile experience works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;User speaks into the device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-time transcription appears.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Within ~2 seconds, structured fluency feedback is displayed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User can switch to roleplay mode for interactive practice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offline mode still provides guidance without AI.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total app size remains around 50MB because no model weights are bundled.&lt;/p&gt;

&lt;p&gt;There is no backend deployment required.&lt;/p&gt;

&lt;p&gt;As the app is still under development and currently running in a stealth environment, I’ve recorded a &lt;a href="https://youtu.be/dL7aEsNekwU" rel="noopener noreferrer"&gt;demo video&lt;/a&gt; instead.&lt;/p&gt;

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

&lt;p&gt;This journey reshaped how I think about mobile AI systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technical lessons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Offline LLMs are viable but operationally heavy on mobile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quantization reduces size but impacts reasoning quality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Latency matters more than locality in speech applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prompt engineering can replace backend microservices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Structured schema prompts significantly improve reliability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Architectural lessons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Community insight can accelerate decision-making.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hackathon validation can clarify real-world constraints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hybrid systems are often more resilient than extreme designs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Engineering maturity is about choosing the right complexity level.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Strong instruction following with structured JSON outputs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fast response times suitable for speech workflows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supportive and adaptive tone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean SDK integration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No infrastructure management overhead&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gemini 2.5 Flash offered a practical balance between speed and reasoning depth.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Where I Experienced Friction&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Occasional JSON formatting drift requiring defensive parsing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Free-tier rate limits needing UX consideration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet dependency for advanced features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User onboarding for API key setup&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, compared to embedding large LLMs directly into a mobile app, these trade-offs were manageable.&lt;/p&gt;

&lt;p&gt;This project started with an attempt to push fully offline mobile LLMs.&lt;/p&gt;

&lt;p&gt;After community feedback, a hackathon build, and real-world validation, it evolved into a privacy-first hybrid architecture powered by Google Gemini.&lt;/p&gt;

&lt;p&gt;The biggest lesson was not about compression or inference tricks.&lt;/p&gt;

&lt;p&gt;It was about architectural judgment.&lt;/p&gt;

&lt;p&gt;Sometimes the most advanced system is the one with the fewest moving parts.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>geminireflections</category>
      <category>gemini</category>
      <category>llm</category>
    </item>
    <item>
      <title>Tech for good, built and shared on DEV 💛. 

I built a stutter-friendly app for calm, supportive, judgment-free speaking practice, with gentle feedback and privacy-first design at its core.

Built with Elm, Elixir, and Copilot CLI. Thoughts?</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Fri, 20 Feb 2026 23:22:59 +0000</pubDate>
      <link>https://forem.com/ujja/tech-for-good-built-and-shared-on-dev-i-built-a-stutter-friendly-app-for-calm-supportive-2e5n</link>
      <guid>https://forem.com/ujja/tech-for-good-built-and-shared-on-dev-i-built-a-stutter-friendly-app-for-calm-supportive-2e5n</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ujja/i-build-a-stutter-friendly-app-in-1-day-with-elm-elixir-and-copilot-24a" class="crayons-story__hidden-navigation-link"&gt;I built a Stutter-Friendly App in 1 Day with Elm, Elixir, and Copilot&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/ujja/i-build-a-stutter-friendly-app-in-1-day-with-elm-elixir-and-copilot-24a" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;GitHub Copilot CLI Challenge Submission&lt;/p&gt;

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

          &lt;a href="/ujja" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" alt="ujja profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ujja" class="crayons-story__secondary fw-medium m:hidden"&gt;
              ujja
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                ujja
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3256184" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ujja" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F439943%2F774d42c6-75e1-4247-8688-30020ce8f40a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;ujja&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ujja/i-build-a-stutter-friendly-app-in-1-day-with-elm-elixir-and-copilot-24a" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 14&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ujja/i-build-a-stutter-friendly-app-in-1-day-with-elm-elixir-and-copilot-24a" id="article-link-3256184"&gt;
          I built a Stutter-Friendly App in 1 Day with Elm, Elixir, and Copilot
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/githubchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;githubchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cli"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cli&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/githubcopilot"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;githubcopilot&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ujja/i-build-a-stutter-friendly-app-in-1-day-with-elm-elixir-and-copilot-24a" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;44&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ujja/i-build-a-stutter-friendly-app-in-1-day-with-elm-elixir-and-copilot-24a#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              16&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            9 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>Is Creativity Dying in the Age of AI-Generated Websites?</title>
      <dc:creator>ujja</dc:creator>
      <pubDate>Wed, 18 Feb 2026 02:49:22 +0000</pubDate>
      <link>https://forem.com/ujja/is-creativity-dying-in-the-age-of-ai-generated-websites-5bmi</link>
      <guid>https://forem.com/ujja/is-creativity-dying-in-the-age-of-ai-generated-websites-5bmi</guid>
      <description>&lt;p&gt;Lately, I’ve been noticing a curious trend. I visit one website, and then another, and… it’s almost the same. Layouts feel eerily familiar, interactions feel almost identical, and the overall "feel" is uncanny. What’s even more striking is that many of these sites have emerged in just the last year or two.  &lt;/p&gt;

&lt;p&gt;It makes me wonder. Is AI actually stifling creativity? Or is it just accelerating convergence in design?  &lt;/p&gt;

&lt;p&gt;Many of these websites appear to be built end-to-end with AI-assisted tools. From layout to copy to interaction patterns, it feels like someone hit a "VibeCode" button and got the whole package. The upside is obvious. Faster development, consistent quality, and lower cost. The downside? They all start to look and feel the same.  &lt;/p&gt;

&lt;p&gt;I could be wrong, but it seems like the proliferation of these AI-driven templates might be leading to a kind of homogenisation. The uniqueness that used to come from a designer’s experimentation or a developer’s creative twist is now being replaced by AI "best practices." &lt;/p&gt;

&lt;p&gt;That’s not to say AI is inherently bad for innovation. It can supercharge ideas, help smaller teams punch above their weight, and unlock possibilities that were previously too time-consuming. But if everyone leans too heavily on AI-generated defaults, we might end up in a world where every new site looks like a slightly different clone of the last one.  &lt;/p&gt;

&lt;p&gt;So maybe the real challenge isn’t AI itself. It’s how we &lt;em&gt;use&lt;/em&gt; it. If we rely on it blindly, innovation can stagnate. But if we treat it as a creative partner, a tool rather than a template factory, there’s still room for fresh ideas, bold experiments, and genuine originality.  &lt;/p&gt;

&lt;p&gt;The question I keep coming back to is this. In a world where AI can do "most of it" automatically, how do we ensure we’re still pushing boundaries instead of just reproducing what already exists?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>vibecoding</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
