<?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: Enrique Uribe</title>
    <description>The latest articles on Forem by Enrique Uribe (@uribejr).</description>
    <link>https://forem.com/uribejr</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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg</url>
      <title>Forem: Enrique Uribe</title>
      <link>https://forem.com/uribejr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/uribejr"/>
    <language>en</language>
    <item>
      <title>AdblockNot - The Adblocker you've never wanted.</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Sat, 11 Apr 2026 22:13:14 +0000</pubDate>
      <link>https://forem.com/uribejr/adblocknot-the-adblock-youve-never-wanted-c00</link>
      <guid>https://forem.com/uribejr/adblocknot-the-adblock-youve-never-wanted-c00</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;h1&gt;
  
  
  Adblock Not
&lt;/h1&gt;

&lt;p&gt;Have you ever sat there watching a youtube ad and said "dang, I just wish there were more ads?" Welcome to AdblockNot!&lt;/p&gt;

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

&lt;p&gt;I built &lt;code&gt;Adblock Not&lt;/code&gt;, the ad blocker you've never wanted.&lt;/p&gt;

&lt;p&gt;Most ad blockers try to make the web less annoying. &lt;code&gt;Adblock Not&lt;/code&gt; takes the opposite approach. It sees your desire for an ad-free experience and responds with the worst possible product decision: before it blocks ads, it makes you watch one.&lt;/p&gt;

&lt;p&gt;Not a skippable one, either.&lt;/p&gt;

&lt;p&gt;To make this bad idea feel more official, I wrapped the whole thing in a fake early-2000s cable/satellite interface. The overlay looks like a retro TV guide, the ads are presented like channels, and if you do not like the current ad, you can always change the channel to a different ad.&lt;/p&gt;

&lt;p&gt;I also wanted it to tap into a very specific kind of commercial nostalgia: the era of weird infomercials, overdramatic voiceovers, late-night paid programming, and commercials you did not exactly love, but somehow still remember forever.&lt;/p&gt;

&lt;p&gt;That is the entire value proposition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it is an ad blocker built on a terrible premise&lt;/li&gt;
&lt;li&gt;it treats ad blocking like premium content authorization&lt;/li&gt;
&lt;li&gt;it adds friction where absolutely none was needed&lt;/li&gt;
&lt;li&gt;it is less a utility and more a hostage negotiation with nostalgic television design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current lineup includes multiple gloriously inconvenient commercials, including &lt;code&gt;Fushigi&lt;/code&gt;, &lt;code&gt;Education Connection&lt;/code&gt;, &lt;code&gt;Nike Football&lt;/code&gt;, &lt;code&gt;Sears&lt;/code&gt;, and &lt;code&gt;Zoobooks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So yes: I made software whose core feature is disrespecting your time in a more organized and stylish way.&lt;/p&gt;

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

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3mmtzb6coacqsmmrxub.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%2Fr3mmtzb6coacqsmmrxub.png" alt="adblocknot_fushigi_commercial" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfphd2ghz0oe9bacz4qv.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%2Fmfphd2ghz0oe9bacz4qv.png" alt="adblocknot_channelguide" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1ozmkogizy862yunzdj.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%2Fg1ozmkogizy862yunzdj.png" alt="adblocknot_nike_football_commercial" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/UribeJr" rel="noopener noreferrer"&gt;
        UribeJr
      &lt;/a&gt; / &lt;a href="https://github.com/UribeJr/adblocknot" rel="noopener noreferrer"&gt;
        adblocknot
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Adblock Not&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Adblock Not&lt;/code&gt; is the ad blocker you've never wanted.&lt;/p&gt;
&lt;p&gt;It is a joke Chrome MV3 extension built around a deliberately terrible idea: before it blocks ads, it makes you watch an ad. To make the experience feel more official, the whole gate is wrapped in a retro early-2000s TV interface with channel switching, a fake guide, and a lineup of bundled commercials.&lt;/p&gt;
&lt;p&gt;This is not a serious ad blocker. It is an anti-product with excellent commitment to the bit.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What It Does&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Detects when a page should show the &lt;code&gt;Adblock Not&lt;/code&gt; gate.&lt;/li&gt;
&lt;li&gt;Opens a fullscreen retro TV-style overlay before ad blocking is allowed.&lt;/li&gt;
&lt;li&gt;Makes you watch one of several bundled ad videos to completion, or wait through a fallback timer if playback fails.&lt;/li&gt;
&lt;li&gt;Lets you "change the channel" to a different ad, which is obviously not real relief.&lt;/li&gt;
&lt;li&gt;Includes a retro guide UI so you can manually pick…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/UribeJr/adblocknot" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;&lt;code&gt;Adblock Not&lt;/code&gt; is a Chrome Manifest V3 extension built with plain JavaScript, HTML, and CSS.&lt;/p&gt;

&lt;p&gt;The basic idea was simple: if an ad blocker is supposed to remove interruptions, I wanted to build one that introduces a brand new interruption first.&lt;/p&gt;

&lt;p&gt;The extension injects a fullscreen content-script overlay onto pages, then uses a background service worker to track whether the user has satisfied the completely unnecessary ad-watching requirement.&lt;/p&gt;

&lt;p&gt;Main pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;manifest.json&lt;/code&gt; wires up the MV3 extension, content script, service worker, and bundled media assets.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/content/gate-overlay.js&lt;/code&gt; renders the fake TV UI, loads the bundled ad videos, handles channel switching, opens the guide, and controls the unlock flow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/content/gate-overlay.css&lt;/code&gt; gives the whole experience the retro cable-box look.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/background/service-worker.js&lt;/code&gt; stores unlock state and decides whether the gate should appear.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of my favorite details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The entire joke works because the product logic is coherent. Every part of it is committed to making ad blocking slightly more annoying.&lt;/li&gt;
&lt;li&gt;The guide UI is based on old cable/satellite channel guides because that era already felt one tiny step away from self-parody.&lt;/li&gt;
&lt;li&gt;The bundled ads are part of the joke, but they are also part of the nostalgia. They come from that very specific "how is this on television again?" era of commercials that burned themselves into your brain.&lt;/li&gt;
&lt;li&gt;The video player uses custom controls to keep the fake-TV vibe intact.&lt;/li&gt;
&lt;li&gt;"Change the channel" is my favorite feature because it sounds like a mercy feature, but it is actually just a different route to the same suffering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically, it was also a fun constraint: make something that is dumb on purpose, but polished enough that the joke lands immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Category
&lt;/h2&gt;

&lt;p&gt;Primary category:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Community Favorite&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why:&lt;/p&gt;

&lt;p&gt;I built this as a pure anti-product. The concept is immediate, the joke is obvious, and the whole thing is committed to the bit: an ad blocker that forces you to watch ads before it helps you avoid ads.&lt;/p&gt;

&lt;p&gt;Alternate category I could also argue for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Best Ode to Larry Masinter&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why:&lt;/p&gt;

&lt;p&gt;The project is built in the spirit of lovingly useless internet/software humor. It is not practical, it is not responsible, and it is absolutely committed to the bit.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Good luck to all the winners! This was fun to dive into as a pretty 'basic' notion user. MCP really helped learn the ins and outs of what notion can provide.</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Wed, 01 Apr 2026 18:24:29 +0000</pubDate>
      <link>https://forem.com/uribejr/good-luck-to-all-the-winners-this-was-fun-to-dive-into-as-a-pretty-basic-notion-user-mcp-really-45no</link>
      <guid>https://forem.com/uribejr/good-luck-to-all-the-winners-this-was-fun-to-dive-into-as-a-pretty-basic-notion-user-mcp-really-45no</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" class="crayons-story__hidden-navigation-link"&gt;I built an AI behavioral Brain with Notion MCP&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" alt="uribejr profile" class="crayons-avatar__image" width="800" height="856"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/uribejr" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Enrique Uribe
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Enrique Uribe
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3416869" 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" class="crayons-avatar__image" alt="" width="800" height="856"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Enrique Uribe&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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" id="article-link-3416869"&gt;
          I built an AI behavioral Brain with Notion MCP
        &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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" 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="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;12&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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6#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>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Mon, 30 Mar 2026 15:20:22 +0000</pubDate>
      <link>https://forem.com/uribejr/-1hd7</link>
      <guid>https://forem.com/uribejr/-1hd7</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" class="crayons-story__hidden-navigation-link"&gt;I built an AI behavioral Brain with Notion MCP&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" alt="uribejr profile" class="crayons-avatar__image" width="800" height="856"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/uribejr" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Enrique Uribe
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Enrique Uribe
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3416869" 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" class="crayons-avatar__image" alt="" width="800" height="856"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Enrique Uribe&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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" id="article-link-3416869"&gt;
          I built an AI behavioral Brain with Notion MCP
        &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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" 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="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;12&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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6#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>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Sat, 28 Mar 2026 14:01:25 +0000</pubDate>
      <link>https://forem.com/uribejr/-den</link>
      <guid>https://forem.com/uribejr/-den</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" class="crayons-story__hidden-navigation-link"&gt;I built an AI E-Commerce Brain with Notion MCP&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" alt="uribejr profile" class="crayons-avatar__image" width="800" height="856"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/uribejr" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Enrique Uribe
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Enrique Uribe
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3416869" 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" class="crayons-avatar__image" alt="" width="800" height="856"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Enrique Uribe&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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" id="article-link-3416869"&gt;
          I built an AI E-Commerce Brain with Notion MCP
        &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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6" 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="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;7&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/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6#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>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>I built an AI behavioral Brain with Notion MCP</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Fri, 27 Mar 2026 20:30:12 +0000</pubDate>
      <link>https://forem.com/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6</link>
      <guid>https://forem.com/uribejr/i-built-an-ai-e-commerce-brain-with-notion-mcp-4bi6</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;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built an AI e-commerce brain for a Shopify storefront using Notion MCP as the behavior control layer.&lt;/p&gt;

&lt;p&gt;On the surface, it looks like one shopping assistant. Under the hood, it behaves more like a network of specialists:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a training bag specialist&lt;/li&gt;
&lt;li&gt;a gloves and wraps specialist&lt;/li&gt;
&lt;li&gt;a cart review specialist&lt;/li&gt;
&lt;li&gt;an order history specialist&lt;/li&gt;
&lt;li&gt;an add-to-cart specialist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architecture is split intentionally.&lt;/p&gt;

&lt;p&gt;The app keeps ownership of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;intent classification and routing&lt;/li&gt;
&lt;li&gt;Shopify integration&lt;/li&gt;
&lt;li&gt;ranking and filtering&lt;/li&gt;
&lt;li&gt;session and conversation state&lt;/li&gt;
&lt;li&gt;validation and fallback logic&lt;/li&gt;
&lt;li&gt;performance and caching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notion owns the behavior layer for each intent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tone and voice&lt;/li&gt;
&lt;li&gt;intent instructions&lt;/li&gt;
&lt;li&gt;recommendation strategy&lt;/li&gt;
&lt;li&gt;questions to ask&lt;/li&gt;
&lt;li&gt;do / do not rules&lt;/li&gt;
&lt;li&gt;example responses&lt;/li&gt;
&lt;li&gt;behavior notes&lt;/li&gt;
&lt;li&gt;synced intent synonyms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means I can change how the AI behaves per scenario without rewriting prompts throughout the codebase.&lt;/p&gt;

&lt;p&gt;Instead of one generic chatbot, I now have a commerce system made up of specialist branches like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;search_training_bags&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;search_gloves_wraps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cart_review&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;orders_selection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;order_detail&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the behavior visible, editable, and operational.&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%2Fes8tqbm2jiis8r4x09ju.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%2Fes8tqbm2jiis8r4x09ju.png" alt="preview of notion dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also built a publish model so Notion is safe to use in production:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit behavior in Notion&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Sync from Notion&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Publish the behavior into the app&lt;/li&gt;
&lt;li&gt;Run the storefront from the published config locally for fast runtime performance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I also built the reverse flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Sync to Notion&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the app can push its current behavior definitions back into the Notion database.&lt;/p&gt;

&lt;p&gt;This turned Notion from a documentation layer into a real control plane for the AI.&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%2Fu8s2eyv5e7tqdm0j243o.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%2Fu8s2eyv5e7tqdm0j243o.png" alt="notion sync flow"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In the demo, I walk through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the Notion behavior control panel&lt;/li&gt;
&lt;li&gt;the specialist intent rows&lt;/li&gt;
&lt;li&gt;the sync workflow&lt;/li&gt;
&lt;li&gt;changing behavior in Notion and seeing the storefront assistant respond differently&lt;/li&gt;
&lt;li&gt;category-specific shopping flows like training bags and gloves/wraps&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;h3&gt;
  
  
  Parse Notion rows into behavior config
&lt;/h3&gt;

&lt;p&gt;This is the layer that turns a Notion database row into a specialist behavior object the app can use at runtime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parseNotionBehaviorRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;intent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeIntentKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;enabledRaw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enabled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;enabledRaw&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;enabledRaw&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;intentSynonyms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;intent_synonyms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;synonyms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trigger_phrases&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;toneVoice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tone_voice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;voice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;intentInstructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;intent_instructions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;instructions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;questionsToAsk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;questions_to_ask&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;questions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;recommendationStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;product_recommendation_strategy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recommendation_strategy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;doRules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;do&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;do_rules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;doNotRules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;do_not&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;do_not_rules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;upsellCrossSellStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;upsell_cross_sell_strategy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;upsell_strategy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cross_sell_strategy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;exampleResponses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example_responses&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;examples&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;behaviorNotes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pickProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;behavior_notes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sync behavior from Notion into the app
&lt;/h3&gt;

&lt;p&gt;This is the publish step. It pulls the latest behavior definitions from Notion and stores a published config in the app for fast local runtime use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;syncChatBehaviorFromNotion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchNotionBehaviorDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publishedConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizePublishedBehaviorConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;published_notion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;publishedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;updateSettings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;behaviorConfigJson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publishedConfig&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;behaviorConfigSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;publishedConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;behaviorSyncedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;behaviorCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;shop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;publishedConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;expiresAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOTION_BEHAVIOR_CACHE_MS&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_CACHE_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_CACHE_MS&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;publishedConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sync behavior back to Notion
&lt;/h3&gt;

&lt;p&gt;This is the reverse direction. It pushes app-side behavior definitions back into the Notion control panel so the system stays visible and editable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;syncChatBehaviorToNotion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sanitizeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOTION_API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;databaseId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sanitizeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOTION_BEHAVIOR_DATABASE_ID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;databaseId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Missing NOTION_API_TOKEN or NOTION_BEHAVIOR_DATABASE_ID.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shop&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getSettings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publishedConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseBehaviorConfigJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;behaviorConfigJson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;cloneDefaultConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;effectiveConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizePublishedBehaviorConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;publishedConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;publishedConfig&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;published&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingRows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;queryNotionBehaviorRows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;databaseId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rowMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;existingRows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseNotionBehaviorRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;rowMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;effectiveConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intents&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;intentKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;intents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mergedBehavior&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;effectiveConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}),&lt;/span&gt;
      &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;behavior&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildNotionBehaviorProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intentKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mergedBehavior&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingPageId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rowMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intentKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existingPageId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;updateNotionBehaviorPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;existingPageId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createNotionBehaviorPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;databaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pushedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;intentCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;intents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Runtime behavior loading in storefront chat
&lt;/h3&gt;

&lt;p&gt;This is where the storefront chat loads the published behavior config for the active shop before generating a response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;behaviorConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getChatBehaviorConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shopDomain&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;shop&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then later, the response generator uses the active specialist behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateAssistantCopy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;allowFollowups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;policyAnswer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chatHistory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="nx"&gt;behaviorConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;behaviorIntent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... build shortlist and conversation context ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recommendationInstruction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;behaviorIntent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;search_training_bags&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;trainingBagFollowupInstruction&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;standardFollowupInstruction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// behaviorConfig + behaviorIntent shape the final response&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Admin actions for the two sync buttons
&lt;/h3&gt;

&lt;p&gt;This is the UI-facing action layer that powers Sync From Notion and Sync To Notion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actionType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;action&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;actionType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sync_behavior_to_notion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;syncChatBehaviorToNotion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;behaviorPush&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;pushedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;pushedAt&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Behavior pushed to Notion for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;intentCount&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; intents.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actionType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sync_behavior_from_notion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;syncChatBehaviorFromNotion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;behaviorSync&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;published_notion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;syncedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;publishedAt&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;fetchedAt&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Behavior synced from Notion.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Notion MCP is what made this system possible in a meaningful way.&lt;/p&gt;

&lt;p&gt;I used Notion MCP to create and operate a behavior database that acts like a control room for the storefront AI.&lt;/p&gt;

&lt;p&gt;Each row in Notion represents an intent or a specialized branch, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;search&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;search_training_bags&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;search_gloves_wraps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cart_review&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;orders_selection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;order_detail&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each row contains structured behavior fields like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Tone Voice&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Intent Synonyms&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Intent Instructions&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Questions To Ask&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Product Recommendation Strategy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Do&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Do Not&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Example Responses&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Behavior Notes&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This let me turn Notion into an operator-facing behavior system instead of just a place to store notes.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;the training bag specialist can focus on freestanding vs hanging bag decisions&lt;/li&gt;
&lt;li&gt;the gloves and wraps specialist can focus on MMA gloves, boxing gloves, bag gloves, wraps, padding, and protection&lt;/li&gt;
&lt;li&gt;the cart review specialist can behave more like a checkout assistant&lt;/li&gt;
&lt;li&gt;the order specialists can stay concise and service-oriented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is that Notion MCP did not just help me document the system. It helped me build the system that controls the AI behavior.&lt;/p&gt;

&lt;p&gt;That unlocked a much stronger workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;identify a weak response&lt;/li&gt;
&lt;li&gt;update the specialist behavior in Notion&lt;/li&gt;
&lt;li&gt;sync it into the app&lt;/li&gt;
&lt;li&gt;test it live in the storefront&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why I think this is a strong Notion MCP use case.&lt;/p&gt;

&lt;p&gt;I did not just connect Notion to an agent.&lt;br&gt;
I used Notion MCP to build the behavior control plane for an AI commerce brain.&lt;/p&gt;

&lt;p&gt;Cart Review Behavior:&lt;br&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%2Fqd6ekt1ftt564u9nfhms.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%2Fqd6ekt1ftt564u9nfhms.png" alt="cart review behavior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sale Search Behavior&lt;br&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%2Fdco267lk2s6gll3cybne.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%2Fdco267lk2s6gll3cybne.png" alt="sale search behavior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The part I like most is that behavior is no longer buried in prompts or scattered across code. Notion became a real operating surface for the AI, and that made the storefront feel less like a chatbot and more like a system of specialists that can actually be tuned, tested, and improved over time.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>🧠 My 2026 Shopify Stack — I Don’t Build Apps, I Build Business Solutions</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Tue, 24 Feb 2026 20:47:03 +0000</pubDate>
      <link>https://forem.com/uribejr/my-2026-shopify-stack-i-dont-build-apps-i-build-business-solutions-m4p</link>
      <guid>https://forem.com/uribejr/my-2026-shopify-stack-i-dont-build-apps-i-build-business-solutions-m4p</guid>
      <description>&lt;p&gt;I don’t build Shopify apps for fun.&lt;/p&gt;

&lt;p&gt;I build systems that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automate operations&lt;/li&gt;
&lt;li&gt;Reduce manual work&lt;/li&gt;
&lt;li&gt;Protect revenue&lt;/li&gt;
&lt;li&gt;Increase AOV&lt;/li&gt;
&lt;li&gt;Clean up messy workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shopify is just the platform.&lt;/p&gt;

&lt;p&gt;The real goal is solving business problems.&lt;/p&gt;

&lt;p&gt;This is the stack I use every day to do that.&lt;/p&gt;




&lt;h2&gt;
  
  
  1️⃣ Shopify CLI — The Operational Backbone
&lt;/h2&gt;

&lt;p&gt;Every solution starts here.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shopify app init&lt;/code&gt;&lt;br&gt;
&lt;code&gt;shopify app dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That one workflow covers the things that usually break first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth&lt;/li&gt;
&lt;li&gt;Local development&lt;/li&gt;
&lt;li&gt;Environment wiring&lt;/li&gt;
&lt;li&gt;Fast iteration loops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you’re shipping revenue-impacting logic, fragile setup is a liability.&lt;/p&gt;

&lt;p&gt;CLI keeps the foundation predictable.&lt;/p&gt;


&lt;h2&gt;
  
  
  2️⃣ Shopify MCP — Build Against Reality, Not Assumptions
&lt;/h2&gt;

&lt;p&gt;Most bugs happen because developers assume store structure.&lt;/p&gt;

&lt;p&gt;I don’t assume. I inspect.&lt;/p&gt;

&lt;p&gt;Before building logic around products or metafields, I look at what actually exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {
  products(first: 3) {
    edges {
      node {
        id
        title
        metafields(first: 10) {
          edges {
            node {
              namespace
              key
              type
            }
          }
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I’m working with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real namespaces
&lt;/li&gt;
&lt;li&gt;Real types
&lt;/li&gt;
&lt;li&gt;Real data patterns
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When business logic depends on structure, guessing gets expensive.&lt;/p&gt;




&lt;h2&gt;
  
  
  3️⃣ Admin GraphQL API — Precision Over Noise
&lt;/h2&gt;

&lt;p&gt;Business solutions need precision.&lt;/p&gt;

&lt;p&gt;Example: auto-tag high-value orders so the ops team can prioritize them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mutation = `
mutation AddOrderTag($id: ID!, $tags: [String!]!) {
  tagsAdd(id: $id, tags: $tags) {
    node { id }
    userErrors { field message }
  }
}
`;

const response = await admin.graphql(mutation, {
  variables: {
    id: orderId,
    tags: ["Priority"]
  }
});

const data = await response.json();

if (data.data.tagsAdd.userErrors.length &amp;gt; 0) {
  console.error(data.data.tagsAdd.userErrors);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Small example. Real impact.&lt;/p&gt;

&lt;p&gt;GraphQL lets me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scope tightly&lt;/li&gt;
&lt;li&gt;Avoid overfetching&lt;/li&gt;
&lt;li&gt;Control exactly what the system does&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When thousands of events are flowing through your app, precision matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  4️⃣ Webhooks — Event-Driven Automation
&lt;/h2&gt;

&lt;p&gt;I don’t poll.&lt;/p&gt;

&lt;p&gt;I react.&lt;/p&gt;

&lt;p&gt;Most business automation is event-based:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Orders&lt;/li&gt;
&lt;li&gt;Product updates&lt;/li&gt;
&lt;li&gt;Customer creation&lt;/li&gt;
&lt;li&gt;App uninstall events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Minimal webhook skeleton:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { authenticate } from "../shopify.server";

export const action = async ({ request }) =&amp;gt; {
  const { topic, payload, shop } = await authenticate.webhook(request);

  if (topic === "ORDERS_CREATE") {
    console.log(`New order from ${shop}`);

    // Example: run automation logic here
    // await handleOrderAutomation(payload);
  }

  return new Response(null, { status: 200 });
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where Shopify turns into a business operating system.&lt;/p&gt;

&lt;p&gt;The store moves.&lt;br&gt;&lt;br&gt;
Your system responds.&lt;/p&gt;




&lt;h2&gt;
  
  
  5️⃣ Tunneling — Clean Install &amp;amp; Testing Cycles
&lt;/h2&gt;

&lt;p&gt;Business solutions often depend on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth behaving correctly&lt;/li&gt;
&lt;li&gt;Webhooks firing reliably&lt;/li&gt;
&lt;li&gt;Installation flow being clean&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;shopify app dev&lt;/code&gt; handles tunneling seamlessly.&lt;/p&gt;

&lt;p&gt;That means I can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reinstall repeatedly&lt;/li&gt;
&lt;li&gt;Test webhook flows safely&lt;/li&gt;
&lt;li&gt;Simulate real store conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stability during development prevents chaos in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  6️⃣ DevTools — Because Business Owners Notice Speed
&lt;/h2&gt;

&lt;p&gt;If your embedded app slows down the Shopify admin, it won’t survive.&lt;/p&gt;

&lt;p&gt;I constantly inspect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bundle size&lt;/li&gt;
&lt;li&gt;Network waterfalls&lt;/li&gt;
&lt;li&gt;Blocking scripts&lt;/li&gt;
&lt;li&gt;Unnecessary re-renders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Merchants don’t care how elegant your architecture is.&lt;/p&gt;

&lt;p&gt;They care if it feels fast.&lt;/p&gt;

&lt;p&gt;Business impact &amp;gt; technical elegance.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Difference
&lt;/h2&gt;

&lt;p&gt;Anyone can build features.&lt;/p&gt;

&lt;p&gt;Not everyone builds solutions.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Thinking in workflows, not endpoints&lt;/li&gt;
&lt;li&gt;Designing event-driven systems&lt;/li&gt;
&lt;li&gt;Validating store structure before writing logic&lt;/li&gt;
&lt;li&gt;Treating revenue-impacting code with discipline&lt;/li&gt;
&lt;li&gt;Building for scale from day one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shopify is just the canvas.&lt;/p&gt;

&lt;p&gt;The real work is understanding the business behind it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thought
&lt;/h2&gt;

&lt;p&gt;In 2026, Shopify development isn’t about who writes the cleanest code.&lt;/p&gt;

&lt;p&gt;It’s about who designs systems that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Survive scale&lt;/li&gt;
&lt;li&gt;Protect revenue&lt;/li&gt;
&lt;li&gt;Reduce operational friction&lt;/li&gt;
&lt;li&gt;Make merchants’ lives easier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s the stack I build with.&lt;/p&gt;

&lt;p&gt;If you’re building on Shopify — are you building features, or building systems?&lt;/p&gt;

</description>
      <category>shopify</category>
      <category>webdev</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Using banner bear’s AI image creation to automate designer workflows. Check it out!</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Sun, 15 Feb 2026 00:33:53 +0000</pubDate>
      <link>https://forem.com/uribejr/using-banner-bears-ai-image-creation-to-automate-designer-workflows-check-it-out-1dfk</link>
      <guid>https://forem.com/uribejr/using-banner-bears-ai-image-creation-to-automate-designer-workflows-check-it-out-1dfk</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/uribejr" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" alt="uribejr"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/uribejr/automating-email-image-requests-with-asana-zapier-bannerbear-89d" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;🚀 Automating Email Image Requests with Asana + Zapier + BannerBear&lt;/h2&gt;
      &lt;h3&gt;Enrique Uribe ・ Feb 12&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#automation&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#nocode&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#api&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>automation</category>
      <category>nocode</category>
      <category>api</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🚀 Automating Email Image Requests with Asana + Zapier + BannerBear</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Thu, 12 Feb 2026 17:37:31 +0000</pubDate>
      <link>https://forem.com/uribejr/automating-email-image-requests-with-asana-zapier-bannerbear-89d</link>
      <guid>https://forem.com/uribejr/automating-email-image-requests-with-asana-zapier-bannerbear-89d</guid>
      <description>&lt;p&gt;Some companies operate multiple sub-brands under one marketing department.&lt;/p&gt;

&lt;p&gt;Each brand has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its own identity
&lt;/li&gt;
&lt;li&gt;Its own templates
&lt;/li&gt;
&lt;li&gt;Its own dedicated graphic designers
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But most email campaigns follow repeatable patterns — flash sales, limited-time offers, announcements.&lt;/p&gt;

&lt;p&gt;Instead of having designers rebuild the same promo layouts every time, this system automates the repetitive production work while preserving brand control.&lt;/p&gt;

&lt;p&gt;Built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Asana&lt;/strong&gt; → request form intake
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zapier&lt;/strong&gt; → routing + logic
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BannerBear&lt;/strong&gt; → image rendering
&lt;/li&gt;
&lt;/ul&gt;

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




&lt;h2&gt;
  
  
  🧠 The Goal
&lt;/h2&gt;

&lt;p&gt;This wasn’t about replacing designers.&lt;/p&gt;

&lt;p&gt;It was about removing repetitive promo production so designers can focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Campaign concepts
&lt;/li&gt;
&lt;li&gt;Brand evolution
&lt;/li&gt;
&lt;li&gt;High-impact creative
&lt;/li&gt;
&lt;li&gt;Strategic visual storytelling
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Designers build the master templates once.&lt;br&gt;&lt;br&gt;
Automation handles recurring production.&lt;/p&gt;

&lt;p&gt;That shift alone makes a huge difference.&lt;/p&gt;


&lt;h2&gt;
  
  
  🏗 How It Works
&lt;/h2&gt;

&lt;p&gt;Here’s the full workflow from request to finished asset:&lt;/p&gt;
&lt;h3&gt;
  
  
  1️⃣ Marketing Submits a Form
&lt;/h3&gt;

&lt;p&gt;The marketing team fills out a structured form inside Asana.&lt;/p&gt;

&lt;p&gt;That form automatically creates a task in the &lt;strong&gt;Email Image Requests&lt;/strong&gt; project with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Division
&lt;/li&gt;
&lt;li&gt;Template type
&lt;/li&gt;
&lt;li&gt;Promo details
&lt;/li&gt;
&lt;li&gt;Copy
&lt;/li&gt;
&lt;li&gt;Any needed assets
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything starts from one intake system.&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%2Flbla71prebqcysjno9s2.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%2Flbla71prebqcysjno9s2.png" alt="form-example" width="741" height="908"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  2️⃣ Designer Reviews the Request
&lt;/h3&gt;

&lt;p&gt;Each brand has a dedicated designer.&lt;/p&gt;

&lt;p&gt;The assigned designer reviews the task and ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy is correct
&lt;/li&gt;
&lt;li&gt;Template selection makes sense
&lt;/li&gt;
&lt;li&gt;Assets are attached
&lt;/li&gt;
&lt;li&gt;Everything is ready
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it’s approved, the designer moves the task to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Ready to Render”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7tb6ocyn70p43si5nsrx.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%2F7tb6ocyn70p43si5nsrx.png" alt="ready-render-example" width="697" height="629"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  3️⃣ Moving to “Ready to Render” Triggers the Zap
&lt;/h3&gt;

&lt;p&gt;That section change triggers the automation.&lt;/p&gt;

&lt;p&gt;Zapier then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pulls all task data
&lt;/li&gt;
&lt;li&gt;Checks the &lt;strong&gt;Division&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Checks the &lt;strong&gt;Template type&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Maps the task data to the correct BannerBear template &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j3mugdyxe0nifz7atji.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%2F8j3mugdyxe0nifz7atji.png" alt="zap-example" width="800" height="735"&gt;&lt;/a&gt; &lt;/p&gt;


&lt;h3&gt;
  
  
  4️⃣ BannerBear Generates the Image
&lt;/h3&gt;

&lt;p&gt;Zapier sends the mapped data to BannerBear.&lt;/p&gt;

&lt;p&gt;BannerBear renders the image based on the correct brand template.&lt;/p&gt;

&lt;p&gt;No manual design work required.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "template": "V32jY9bBM6l0DBGWrl",
  "modifications": [
    {
      "name": "BG_COLOR",
      "color": null
    },
    {
      "name": "TXT_HEADLINE",
      "text": "You can change this text",
      "color": null,
      "background": null
    },
    {
      "name": "CTA_COLOR",
      "color": null
    },
    {
      "name": "TXT_CTA",
      "text": "You can change this text",
      "color": null,
      "background": null
    },
    {
      "name": "TXT_BODY",
      "text": "You can change this text",
      "color": null,
      "background": null
    },
    {
      "name": "IMG_FEATURED",
      "image_url": "https://cdn.bannerbear.com/sample_images/welcome_bear_photo.jpg"
    },
    {
      "name": "TXT_SUBHEAD",
      "text": "You can change this text",
      "color": null,
      "background": null
    },
    {
      "name": "TXT_LEGAL",
      "text": "You can change this text",
      "color": null,
      "background": null
    }
  ],
  "webhook_url": null,
  "transparent": false,
  "metadata": null
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5️⃣ Zapier Updates the Task
&lt;/h3&gt;

&lt;p&gt;Once the image is created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zapier grabs the generated asset URL
&lt;/li&gt;
&lt;li&gt;Updates a custom field called &lt;strong&gt;“Created Asset”&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The image is ready to download directly from the task
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfb57jb47ozqh0ij7qck.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%2Ftfb57jb47ozqh0ij7qck.png" alt="image-assett-delivered-example" width="694" height="219"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;One intake system.&lt;br&gt;&lt;br&gt;
Multiple brand outputs.&lt;br&gt;&lt;br&gt;
Fully automated.&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%2F5vzbdtpz3htfay4ykfyo.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%2F5vzbdtpz3htfay4ykfyo.png" alt="email-image-example" width="800" height="1266"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>nocode</category>
      <category>api</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Create your own avatar! 👾
I just added a Pixel Avatar Maker to this Windows 98–style portfolio — feel free to share yours in the comments.</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Sun, 25 Jan 2026 01:28:24 +0000</pubDate>
      <link>https://forem.com/uribejr/create-your-own-avatar-i-just-added-a-pixel-avatar-maker-to-this-windows-98-style-portfolio--1jm9</link>
      <guid>https://forem.com/uribejr/create-your-own-avatar-i-just-added-a-pixel-avatar-maker-to-this-windows-98-style-portfolio--1jm9</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/uribejr/lets-build-with-ai-like-its-1998-41kl" class="crayons-story__hidden-navigation-link"&gt;I Built a Windows 98–Style Desktop Portfolio with AI 💾&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/uribejr/lets-build-with-ai-like-its-1998-41kl" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;New Year, New You Portfolio 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" alt="uribejr profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/uribejr" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Enrique Uribe
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Enrique Uribe
                
              
              &lt;div id="story-author-preview-content-3183607" 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Enrique Uribe&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/uribejr/lets-build-with-ai-like-its-1998-41kl" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jan 19&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/uribejr/lets-build-with-ai-like-its-1998-41kl" id="article-link-3183607"&gt;
          I Built a Windows 98–Style Desktop Portfolio with AI 💾
        &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/googleaichallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;googleaichallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/portfolio"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;portfolio&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemini"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemini&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/uribejr/lets-build-with-ai-like-its-1998-41kl" 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;21&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/uribejr/lets-build-with-ai-like-its-1998-41kl#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              6&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;
            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>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>What was your first operating system?</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Tue, 20 Jan 2026 17:56:28 +0000</pubDate>
      <link>https://forem.com/uribejr/-16c3</link>
      <guid>https://forem.com/uribejr/-16c3</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/uribejr" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" alt="uribejr"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/uribejr/lets-build-with-ai-like-its-1998-41kl" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;I Built a Windows 98–Style Desktop Portfolio with AI 💾&lt;/h2&gt;
      &lt;h3&gt;Enrique Uribe ・ Jan 19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devchallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#googleaichallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#portfolio&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#gemini&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>What was your first operating system?</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Tue, 20 Jan 2026 17:55:03 +0000</pubDate>
      <link>https://forem.com/uribejr/what-was-your-first-operating-system-5f8a</link>
      <guid>https://forem.com/uribejr/what-was-your-first-operating-system-5f8a</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/uribejr/lets-build-with-ai-like-its-1998-41kl" class="crayons-story__hidden-navigation-link"&gt;I Built a Windows 98–Style Desktop Portfolio with AI 💾&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/uribejr/lets-build-with-ai-like-its-1998-41kl" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;New Year, New You Portfolio 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" alt="uribejr profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/uribejr" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Enrique Uribe
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Enrique Uribe
                
              
              &lt;div id="story-author-preview-content-3183607" 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="/uribejr" 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%2F1993731%2F9b1659cd-644a-4612-900d-99c815fd152c.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Enrique Uribe&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/uribejr/lets-build-with-ai-like-its-1998-41kl" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jan 19&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/uribejr/lets-build-with-ai-like-its-1998-41kl" id="article-link-3183607"&gt;
          I Built a Windows 98–Style Desktop Portfolio with AI 💾
        &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/googleaichallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;googleaichallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/portfolio"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;portfolio&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemini"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemini&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/uribejr/lets-build-with-ai-like-its-1998-41kl" 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;21&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/uribejr/lets-build-with-ai-like-its-1998-41kl#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              6&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;
            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>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>I Built a Windows 98–Style Desktop Portfolio with AI 💾</title>
      <dc:creator>Enrique Uribe</dc:creator>
      <pubDate>Mon, 19 Jan 2026 23:30:45 +0000</pubDate>
      <link>https://forem.com/uribejr/lets-build-with-ai-like-its-1998-41kl</link>
      <guid>https://forem.com/uribejr/lets-build-with-ai-like-its-1998-41kl</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/new-year-new-you-google-ai-2025-12-31"&gt;New Year, New You Portfolio Challenge Presented by Google AI&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I’m a full-stack developer and digital designer with over a decade of experience building robust, scalable solutions that solve real-world problems. I thrive on both thoughtful architecture and polished design — from concept through deployment — and I’m passionate about creating work that is both technically sound and visually engaging.&lt;/p&gt;

&lt;p&gt;For this challenge, I took a personal and creative direction with my portfolio: a Windows 98-style experience with a MySpace-inspired profile. This project isn’t just a collection of links — it’s a window into who I am as a developer and a creator.&lt;/p&gt;

&lt;p&gt;Growing up in the 90s, Windows 98 was my first computer and one of my earliest influences in computing. The look, sound, and playfulness of those early graphical interfaces sparked my curiosity about how software can be expressive and fun. Likewise, MySpace was the first social platform where I crafted my digital identity, experimented with layout and style, and shared music and stories that mattered to me as a teenager.&lt;/p&gt;

&lt;p&gt;That nostalgia fuels this portfolio: blending retro aesthetics with modern cloud-native tech. I built and deployed this project to Google Cloud Run, leveraging scalable infrastructure and embedding the live site directly in my submission. &lt;/p&gt;

&lt;p&gt;This portfolio reflects my technical skills, creative thinking, and willingness to break conventions — using nostalgia not as a gimmick, but as a thoughtful design lens. I hope it shows not only where I’ve been, but also where I’m going as a developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Portfolio
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://portfolio-98-217733537072.us-central1.run.app/"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;




&lt;p&gt;Take me for a spin!&lt;br&gt;
&lt;a href="https://portfolio-98-217733537072.us-central1.run.app/" rel="noopener noreferrer"&gt;View UribeJr98&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The deployment is hosted on &lt;strong&gt;Google Cloud Run&lt;/strong&gt; and features a custom &lt;code&gt;dev-tutorial&lt;/code&gt; label per the submission guidelines.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔄 Update: Pixel Avatar Maker (New Desktop App)
&lt;/h2&gt;

&lt;p&gt;After publishing this portfolio, I added a new interactive desktop app: a &lt;strong&gt;Pixel Avatar Maker&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Inspired by late-90s and early-2000s pixel art and avatar creators, this app lets you customize a retro pixel character — tweak colors, styles, and details — and export your avatar as a PNG, all within the Windows 98–style OS.&lt;/p&gt;

&lt;p&gt;It’s designed to be lightweight, playful, and instantly understandable. No setup, no rules — just open it, create something, and take it with you. In the spirit of the era, it’s less about perfection and more about expression.&lt;/p&gt;

&lt;p&gt;If you make one, feel free to &lt;strong&gt;share your avatar in the comments&lt;/strong&gt; — I’d love to see what people come up with.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Examples generated using the Pixel Avatar Maker below 👇)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmmtcfelxnlenk58sqxa.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%2Fwmmtcfelxnlenk58sqxa.png" alt="Pixel Avatar Example 1"&gt;&lt;/a&gt;&lt;br&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%2F2qjptakgakvkcrzu507s.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%2F2qjptakgakvkcrzu507s.png" alt="Pixel Avatar Example 2"&gt;&lt;/a&gt;&lt;br&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%2Foyfsfxyy2oj29xjlxr7l.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%2Foyfsfxyy2oj29xjlxr7l.png" alt="Pixel Avatar Example 3"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;This portfolio was built as a fully interactive, OS-style web application, inspired by Windows 98 and early MySpace layouts, but implemented with modern frontend architecture and cloud-native deployment.&lt;/p&gt;

&lt;p&gt;The app is structured around a centralized window manager that controls open state, focus, minimization, and z-index — allowing draggable, overlapping windows similar to a real desktop environment. Each “application” (About Me, Media Player, Projects, Notepad Messenger, Pong, Explorer) is implemented as a self-contained React component, keeping the system modular and extensible.&lt;/p&gt;

&lt;p&gt;The frontend is built with React and Vite for fast development and optimized builds. I used 98.css as a stylistic base and layered custom CSS for responsive behavior, window chrome, and interaction polish. Project case studies open in a dedicated viewer that supports structured data and GitHub-style Markdown rendering, making content easy to maintain while staying on-theme.&lt;/p&gt;

&lt;p&gt;For interactivity, I integrated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A SoundCloud-powered media player&lt;/li&gt;
&lt;li&gt;A Pong mini-game&lt;/li&gt;
&lt;li&gt;A persistent Notepad Messenger&lt;/li&gt;
&lt;li&gt;Desktop icons and a taskbar that mirror classic OS behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In production, the app is served by a lightweight Node.js + Express server, which handles SPA routing and static assets. The project is deployed to Google Cloud Run, demonstrating a modern, scalable deployment model with minimal operational overhead and a live, embeddable URL for the DEV submission.&lt;/p&gt;

&lt;p&gt;The goal was to combine nostalgic design with modern engineering, showing that expressive interfaces and production-ready architecture can coexist.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm Most Proud Of
&lt;/h2&gt;

&lt;p&gt;I’m proud of who I am and where I come from.&lt;/p&gt;

&lt;p&gt;This portfolio acts as a time capsule of my life, capturing the technology, music, and digital spaces that shaped my earliest experiences with computers. Windows 98 was my first operating system, and MySpace was the first place I learned how to express myself online. Those moments sparked my curiosity and influenced how I approach design and interaction today.&lt;/p&gt;

&lt;p&gt;What makes this project meaningful to me is how it connects past and present. I took those formative experiences and rebuilt them using modern tools, thoughtful architecture, and cloud deployment — turning nostalgia into something functional and forward-looking.&lt;/p&gt;

&lt;p&gt;This portfolio isn’t just a collection of projects. It’s a reflection of my journey, preserving where I started while showing who I’ve become as a developer.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
  </channel>
</rss>
