<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Patterson</title>
    <description>The latest articles on DEV Community by Alex Patterson (@codercatdev).</description>
    <link>https://dev.to/codercatdev</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%2F135713%2F3595a216-0b20-4d9e-9313-426f998c6304.jpg</url>
      <title>DEV Community: Alex Patterson</title>
      <link>https://dev.to/codercatdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codercatdev"/>
    <language>en</language>
    <item>
      <title>AJ is Loving Sticker Mule</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Thu, 12 Mar 2026 15:05:26 +0000</pubDate>
      <link>https://dev.to/codingcatdev/aj-is-loving-sticker-mule-4m2b</link>
      <guid>https://dev.to/codingcatdev/aj-is-loving-sticker-mule-4m2b</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/post/aj-is-loving-sticker-mule" rel="noopener noreferrer"&gt;https://codingcat.dev/post/aj-is-loving-sticker-mule&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codingcat.dev/post/aj-is-loving-sticker-mule" rel="noopener noreferrer"&gt;https://codingcat.dev/post/aj-is-loving-sticker-mule&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have tried several sticker places and the images always come back terrible and the customer service stinks. Then I found Sticker Mule and everything has been like a dream! Check out all of their &lt;a href="https://www.stickermule.com/custom-stickers" rel="noopener noreferrer"&gt;custom stickers&lt;/a&gt;​!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;*&lt;a href="https://www.stickermule.com/unlock?ref_id=3730681701&amp;amp;utm_medium=link&amp;amp;utm_source=invite" rel="noopener noreferrer"&gt;Get $10 in Credit from AJ today!&lt;/a&gt;*Loading image...&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  All the stickers a cat could possible need
&lt;/h2&gt;

&lt;p&gt;AJ may have gotten his paws on the keyboard while I was ordering our first set of stickers, but honestly they are such a great deal I still placed the order.&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%2Fr41427nusq2i21rdy4yr.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%2Fr41427nusq2i21rdy4yr.jpg" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Studio Wall Logo
&lt;/h2&gt;

&lt;p&gt;I was so impressed by how the stickers turned out that I had to get a logo for the new studio!&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%2Fk6aqia1rd7qt7ne6ords.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%2Fk6aqia1rd7qt7ne6ords.jpg" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>JAMStackGR</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Thu, 12 Mar 2026 15:03:46 +0000</pubDate>
      <link>https://dev.to/codingcatdev/jamstackgr-a06</link>
      <guid>https://dev.to/codingcatdev/jamstackgr-a06</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/post/jamstackgr-1-sanity-io-as-a-backend" rel="noopener noreferrer"&gt;https://codingcat.dev/post/jamstackgr-1-sanity-io-as-a-backend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codingcat.dev/post/jamstackgr-1-sanity-io-as-a-backend" rel="noopener noreferrer"&gt;https://codingcat.dev/post/jamstackgr-1-sanity-io-as-a-backend&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%2F96sa0dtu1czddrxwdtd5.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%2F96sa0dtu1czddrxwdtd5.jpg" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  JAMStack GR #1
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/presentation/d/1GsitEUyrC0xV4xlpFuRB9QKI5B4hdB5tZ5ldZEbuciU/edit?usp=sharing" rel="noopener noreferrer"&gt;https://docs.google.com/presentation/d/1GsitEUyrC0xV4xlpFuRB9QKI5B4hdB5tZ5ldZEbuciU/edit?usp=sharing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever used Wordpress or Contentful? There is a new Headless CMS that might replace them.&lt;/p&gt;

&lt;p&gt;Distribute a single source of truth to any (all) channel, device or product.&lt;/p&gt;

&lt;p&gt;Sweet Query APIs Prepare data in queries using joins and projections. CDN cache multiple queries in a single request. GraphQL in beta.&lt;/p&gt;

&lt;p&gt;Powerful patching Powerful APIs for patching, exporting, and listening. No locking with real-time syncing.&lt;/p&gt;

&lt;p&gt;Secure &amp;amp; Compliant Fully GDPR Compliant. EU Hosted. Data encrypted at rest and in transit. APIs TLS / SSL only.&lt;/p&gt;

&lt;p&gt;Apps, not ops Sanity is a full-featured content API and editing solution that lets you concentrate on your core business.&lt;/p&gt;

&lt;p&gt;Enterprise comforts Third party login, free-form security rules, transactional writes and millions of documents.&lt;/p&gt;

&lt;p&gt;Scale ready Stop worrying about traffic spikes with asset and API CDNs on every continent – excepting Antarctica.&lt;/p&gt;

&lt;p&gt;Apps, not ops! Sanity is a full-featured content API and editing solution that lets you concentrate on your core business.&lt;/p&gt;

&lt;p&gt;Scale ready. Stop worrying about traffic spikes with asset and API CDNs on every continent – excepting Antarctica.&lt;/p&gt;

&lt;p&gt;Flexible and fast Structured content flows easily across APIs and services, enabling rapid innovation.&lt;/p&gt;

&lt;p&gt;Distribute freely Deep queries with joins on unstructured data. Select and reproject properties. Combine queries into a single cached result on a global CDN.&lt;/p&gt;

&lt;p&gt;Adapt continuously Customize editing environments to fit workflows and quickly iterate on data models.&lt;/p&gt;

&lt;p&gt;Ship fast Sanity is a modern, API-first digital content management system that lets developers work fast using technologies they love&lt;/p&gt;

&lt;p&gt;Customize Sanity is a headless CMS construction kit that you can adapt to create optimal editing experiences.&lt;/p&gt;

&lt;p&gt;Liberate legacy systems Import content in real-time from multiple sources and instantly query across them.&lt;/p&gt;

&lt;p&gt;Create custom editing workflows and experiences Icon for Customize in React.js Customize in React.js Open Source JavaScript editor. Full source code, permissive license.&lt;/p&gt;

&lt;p&gt;Instant UIs for complex data Model your content exactly the way you want with an extensive toolkit.&lt;/p&gt;

&lt;p&gt;Real-time Collaboration Edit structured, highly connected documents collaboratively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@kimbjrkman/how-to-use-inline-images-in-rich-text-with-sanity-io-c42594baa509https://jamstackthemes.dev" rel="noopener noreferrer"&gt;https://medium.com/@kimbjrkman/how-to-use-inline-images-in-rich-text-with-sanity-io-c42594baa509https://jamstackthemes.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Updating AJonP's Brand</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Wed, 04 Mar 2026 21:26:50 +0000</pubDate>
      <link>https://dev.to/codingcatdev/updating-ajonps-brand-2hp8</link>
      <guid>https://dev.to/codingcatdev/updating-ajonps-brand-2hp8</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/post/updating-ajonps-brand" rel="noopener noreferrer"&gt;https://codingcat.dev/post/updating-ajonps-brand&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codingcat.dev/post/updating-ajonps-brand" rel="noopener noreferrer"&gt;https://codingcat.dev/post/updating-ajonps-brand&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another evolution in the AJonP brand has come in the form of standardizing on acceptance. Making the most of neutral (non-stereotyped) colors. Taking a nod from Dev.to and updating AJ's tag to include a rainbow, as every mascot should have gender neutrality.&lt;/p&gt;

&lt;h2&gt;
  
  
  First the Technology
&lt;/h2&gt;

&lt;p&gt;If you have not checked out &lt;a href="https://figma.com/" rel="noopener noreferrer"&gt;Figma&lt;/a&gt; yet please do so right meow! It is so powerful when you can take a component and reuse it throughout your site. Checkout how I can change the eyes in all of these different Logos, just by changing the main component.&lt;a href="https://www.youtube.com/embed/IFLQySh-Zb4?autoplay=0&amp;amp;rel=0&amp;amp;showinfo=0&amp;amp;modestbranding=1" rel="noopener noreferrer"&gt;https://www.youtube.com/embed/IFLQySh-Zb4?autoplay=0&amp;amp;rel=0&amp;amp;showinfo=0&amp;amp;modestbranding=1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AJ's New Tag
&lt;/h2&gt;

&lt;p&gt;AJ will now be representing more people equally, and that is really important particularly to web development! We want a community that encourages everyone to share and learn together!&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%2F29ujlwr3wzoxv14ow6si.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%2F29ujlwr3wzoxv14ow6si.png" width="800" height="793"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Sanity.io to Builder.io Data Transfer</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Wed, 04 Mar 2026 21:25:41 +0000</pubDate>
      <link>https://dev.to/codingcatdev/sanityio-to-builderio-data-transfer-584i</link>
      <guid>https://dev.to/codingcatdev/sanityio-to-builderio-data-transfer-584i</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/post/sanity-io-to-builder-io-data-transfer" rel="noopener noreferrer"&gt;https://codingcat.dev/post/sanity-io-to-builder-io-data-transfer&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%2Fz510i931ov9a6nwxnk84.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%2Fz510i931ov9a6nwxnk84.jpg" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am hoping to make a Sanity.io plugin for builder. In doing so I thought I would write a little conversion tool before hand to figure out all the ins and outs of Builder.io and Sanity.io, so I thought I would share some of my findings. I will keep this tutorial updated as the plugin progresses.&lt;/p&gt;

&lt;p&gt;The repo example has three things that you might find useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deleting All Data&lt;/li&gt;
&lt;li&gt;Creating all new types&lt;/li&gt;
&lt;li&gt;Adding all new Data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Repo for conversion example&lt;/strong&gt; &lt;a href="https://github.com/CodingCatDev/sanity-to-builder.git" rel="noopener noreferrer"&gt;https://github.com/CodingCatDev/sanity-to-builder.git&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting All Data
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/CodingCatDev/sanity-to-builder/blob/84d8b5d436b2d674f916670317cb48de916c8a68/src/index.ts#L175" rel="noopener noreferrer"&gt;https://github.com/CodingCatDev/sanity-to-builder/blob/84d8b5d436b2d674f916670317cb48de916c8a68/src/index.ts#L175&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to delete all the data you need to first find all the models you want to delete&lt;/p&gt;

&lt;h3&gt;
  
  
  Get all Models from Builder (even unpublished)
&lt;/h3&gt;

&lt;p&gt;In sanity you deal with things like &lt;code&gt;draft.&lt;/code&gt; in documents. In Builder these items are just known to be unpublished version. So you need to have &lt;code&gt;includeUnpublished=true&lt;/code&gt; in your API call. I looked for a while in the sdk and have not found this option so far.&lt;/p&gt;

&lt;p&gt;You can handle this by using the fetch command instead of the sdk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/CodingCatDev/sanity-to-builder/blob/84d8b5d436b2d674f916670317cb48de916c8a68/src/config.ts#L134" rel="noopener noreferrer"&gt;https://github.com/CodingCatDev/sanity-to-builder/blob/84d8b5d436b2d674f916670317cb48de916c8a68/src/config.ts#L134&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating all new types
&lt;/h2&gt;

&lt;p&gt;First you need to find all the types in your sanity.io database. I find it best to use Groq. So we can find all the types in Sanity and then create those in Builder as new Models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding all new Data
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Long Term goal
&lt;/h2&gt;

&lt;p&gt;The End goal is to build a plugin for syncing your data...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Builder content link&lt;/strong&gt; &lt;a href="https://github.com/BuilderIO/builder/tree/main/plugins/contentful" rel="noopener noreferrer"&gt;https://github.com/BuilderIO/builder/tree/main/plugins/contentful&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Supabase, Next.js and Builder.io</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Wed, 04 Mar 2026 21:17:30 +0000</pubDate>
      <link>https://dev.to/codingcatdev/supabase-nextjs-and-builderio-5cei</link>
      <guid>https://dev.to/codingcatdev/supabase-nextjs-and-builderio-5cei</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/podcast/supabase-next-js-and-builder-io" rel="noopener noreferrer"&gt;https://codingcat.dev/podcast/supabase-next-js-and-builder-io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>podcast</category>
    </item>
    <item>
      <title>The Purrfect Beginning</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Wed, 04 Mar 2026 21:15:57 +0000</pubDate>
      <link>https://dev.to/codingcatdev/the-purrfect-beginning-3jhb</link>
      <guid>https://dev.to/codingcatdev/the-purrfect-beginning-3jhb</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/podcast/0-0-the-purrfect-beginning" rel="noopener noreferrer"&gt;https://codingcat.dev/podcast/0-0-the-purrfect-beginning&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are on a mission to provide you with the latest tools and trends, that take you from a house cat to a fierce LION.&lt;/p&gt;

&lt;p&gt;Even when your code isn’t feline that good, we ensure you’ll get there with the right cat-i-tude.&lt;/p&gt;

&lt;p&gt;Alright.. Let’s get up and GIT moving..&lt;/p&gt;

&lt;p&gt;Right Meow!!!&lt;/p&gt;

&lt;p&gt;Learning how to be a developer is hard, Purrfect.dev will show you how to grow as a developer bit by bit.&lt;/p&gt;

&lt;p&gt;What We Cover&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JAMStack (Javascript, API, MarkUp)&lt;/li&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;Gaming (Unity)&lt;/li&gt;
&lt;li&gt;Mobile&lt;/li&gt;
&lt;li&gt;AWS, GCP, Azure&lt;/li&gt;
&lt;li&gt;Serverless&lt;/li&gt;
&lt;li&gt;Agile&lt;/li&gt;
&lt;li&gt;Scrum&lt;/li&gt;
&lt;li&gt;Project and Program Management&lt;/li&gt;
&lt;li&gt;Showing developers the successful path&lt;/li&gt;
&lt;li&gt;Quickest way to get PAID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Links&lt;/p&gt;

&lt;p&gt;Send in a voice message: &lt;a href="https://podcasters.spotify.com/pod/show/purrfect-dev/message" rel="noopener noreferrer"&gt;https://podcasters.spotify.com/pod/show/purrfect-dev/message&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>podcast</category>
    </item>
    <item>
      <title>GenAI for Engineers, What's Real, What's Not and What's Coming</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Wed, 19 Nov 2025 13:16:50 +0000</pubDate>
      <link>https://dev.to/codingcatdev/genai-for-engineers-whats-real-whats-not-and-whats-coming-j7p</link>
      <guid>https://dev.to/codingcatdev/genai-for-engineers-whats-real-whats-not-and-whats-coming-j7p</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/podcast/genai-for-engineers-what-s-real-what-s-not-and-what-s-coming" rel="noopener noreferrer"&gt;https://codingcat.dev/podcast/genai-for-engineers-what-s-real-what-s-not-and-what-s-coming&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this post, you’ll understand:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The new engineering landscape GenAI has created&lt;/li&gt;
&lt;li&gt;Practical best practices for leveraging GenAI in your work&lt;/li&gt;
&lt;li&gt;Mistakes and misconceptions you absolutely want to avoid&lt;/li&gt;
&lt;li&gt;Inspiring tools and frameworks that are already changing the game&lt;/li&gt;
&lt;li&gt;What’s on the horizon, both thrilling and a little overwhelming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction: Why GenAI Has Every Engineer Talking
&lt;/h2&gt;

&lt;p&gt;You know the feeling—everyone’s suddenly talking about automation, agents, and how AI is about to revolutionize everything. You read about companies “eliminating jobs” thanks to GenAI, and you’re wondering… Is this really happening? Is this a threat, or is it a huge opportunity?&lt;/p&gt;

&lt;p&gt;If you’ve ever sat with those questions, you’re in good company! On our latest episode, I spoke with Balki, a seasoned CTO, about how GenAI is reshaping engineering roles, what’s actually working in startups right now, and how you can avoid the typical pitfalls to come out ahead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this blog post matters:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;“First time founders focus on product. Successful founders focus on distribution.” — Balki&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That means it’s not just about building with AI—it’s about making it useful, scalable, and profitable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet Balki: Everyday Startup Battles, AI Style
&lt;/h2&gt;

&lt;p&gt;Before we jump into the nitty-gritty, let’s meet our expert guest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Balki's Career: From BigCorp to Fractional CTO
&lt;/h3&gt;

&lt;p&gt;Balki spent his first decade as an engineer at &lt;a href="https://www.fiserv.com" rel="noopener noreferrer"&gt;Fiserv&lt;/a&gt;—deep in the online banking trenches, working primarily on Microsoft’s tech stack. Eventually, he pivoted to leading his own startup, taking the leap from “comfortable” to “complete accountability.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; The happiness came less from money and more from ownership and learning, even when the risks were high.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“There's nobody else to complain about. I’m accountable for everything.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How the Leap Happened (and What You Can Learn)
&lt;/h3&gt;

&lt;p&gt;Far from a sudden “drop everything and start a company,” Balki’s transition was informed by education (an EMBA program) and practical testing. The final pivot occurred in an entrepreneurship course—where building a product from scratch “felt like coming home.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Big jumps are rarely one moment. Often, it’s a series of small pivots, each featuring late-night emails, experimental coding, and a few “blind confidence” moments.&lt;/p&gt;

&lt;h2&gt;
  
  
  CTO Roles: Full-Time, Fractional, and What That Means for Startups
&lt;/h2&gt;

&lt;p&gt;Ever wondered what the difference is between a full-time CTO and a fractional CTO? Balki’s journey is a fascinating example:&lt;/p&gt;

&lt;h3&gt;
  
  
  Full-Time CTO vs. Fractional CTO
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full-Time CTO:&lt;/strong&gt; Committed to one company.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fractional CTO:&lt;/strong&gt; Provides strategic, high-impact guidance to several startups at once—usually part-time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fractional CTOs thrive by:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bringing deep expertise from multiple sectors&lt;/li&gt;
&lt;li&gt;Targeting high-leverage activities (think: 20 hours a month laser-focused on the biggest problems)&lt;/li&gt;
&lt;li&gt;Accelerating product clarity and distribution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Big insight:&lt;/strong&gt; Every minute counts. When you’re dropping in for a few hours a week, priorities become crystal clear!&lt;/p&gt;

&lt;h2&gt;
  
  
  GenAI for Engineers: From “Just Another Tool” To Business Superpower
&lt;/h2&gt;

&lt;p&gt;GenAI isn’t new—but the &lt;em&gt;way&lt;/em&gt; it’s used by engineering teams is evolving fast. Balki says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The market is flooded with proof-of-concept tools targeting non-engineers. In my world, there’s a big chasm between building a prototype, getting traction, and scaling.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can hack together a quick POC with &lt;a href="https://www.lovelace.ai/" rel="noopener noreferrer"&gt;Lovelace&lt;/a&gt; or &lt;a href="https://bolt.new/" rel="noopener noreferrer"&gt;Bolt&lt;/a&gt; in minutes. But scaling that prototype—making it reliable, distributable, and profitable—is a different sport.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Scaling Is So Hard (and Where GenAI Can Help)
&lt;/h3&gt;

&lt;p&gt;Most startups stall, even after they get initial traction. Balki specializes in bridging this “chasm”—helping teams go from “scrappy” to “scalable.”&lt;/p&gt;

&lt;h2&gt;
  
  
  “Engineering Excellence”: Balki’s Five Pillars + GenAI
&lt;/h2&gt;

&lt;p&gt;Let’s get super practical. Any successful engineering team needs &lt;em&gt;engineering excellence&lt;/em&gt;. Before GenAI, Balki set out four pillars. With GenAI, a fifth was added. Here’s the breakdown:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Four Classic Pillars
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Automated Testing&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Validates code. Makes sure your software can withstand real-world scenarios.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Pipelines&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Enables drama-free code deployments.&lt;/li&gt;
&lt;li&gt;Example: &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Let’s engineers be the &lt;em&gt;first&lt;/em&gt; to know when something breaks (not your customers).&lt;/li&gt;
&lt;li&gt;Example: &lt;a href="https://www.datadoghq.com/" rel="noopener noreferrer"&gt;Datadog&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular Architecture&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Flexible, scalable code organization—critical for rapid evolution.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Fifth Pillar: GenAI Fluency
&lt;/h3&gt;

&lt;p&gt;Today, &lt;em&gt;GenAI fluency&lt;/em&gt; is just as critical. In fact, Balki breaks this down further into three sub-pillars (detailed below).&lt;/p&gt;

&lt;h4&gt;
  
  
  Why GenAI Matters
&lt;/h4&gt;

&lt;p&gt;Thanks to GenAI, startups can rapidly accelerate improvement in these pillars—without blowing the budget or risking bankruptcy. You can stay agile and address technical debt much faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  GenAI and Job Roles: Are We Really Automating Ourselves Out?
&lt;/h2&gt;

&lt;p&gt;The media loves to declare “X jobs eliminated by GenAI!”—but is this really the story?&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Actually Changing in Engineering
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Specialization is risky.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Engineers who only focus on one niche (e.g., frontend specialist, TypeScript expert) are seeing those tasks rapidly commoditized.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“For 20 years it was similar—good engineers could rest on their laurels. Now that’s been commoditized. Founder mindset is what matters.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Full-stack skills&lt;/strong&gt; are becoming standard. The ability to build, deploy, test, and validate end-to-end is the new norm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what tasks are ripe for GenAI automation today?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Balki notes: pure specialization may soon be obsolete, and “mundane tasks” (like repetitive API wrappers, boilerplate code, out-of-date documentation) are prime targets for automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Example: API Wrappers &amp;amp; SDKs
&lt;/h3&gt;

&lt;p&gt;Many engineers are scrambling to build “MCP servers”—wrappers around APIs and OpenAI SDKs. With the release of the &lt;a href="https://developers.openai.com/apps-sdk/" rel="noopener noreferrer"&gt;OpenAI App SDK&lt;/a&gt;, a new “walled garden” effect is emerging. Is this healthy? Are we risking another App Store scenario?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s still hard to say if this is a passing trend or a lasting shift.&lt;/strong&gt; For B2B SaaS, the immediate risk may be low, but keeping up AI fluency is more important than ever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering AI Fluency: Climbing the Three GenAI Sub-Pillars
&lt;/h2&gt;

&lt;p&gt;What does “AI fluency” really mean for engineering teams? Balki’s framework divides it into three practical levels:&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 1: Leveraging AI Tools for Engineer Productivity
&lt;/h3&gt;

&lt;p&gt;This is all about using AI tools—like &lt;a href="https://www.cursor.so/" rel="noopener noreferrer"&gt;Cursor&lt;/a&gt;, &lt;a href="https://www.claude.com/product/claude-code" rel="noopener noreferrer"&gt;Claud Code&lt;/a&gt;, &lt;a href="https://coderabbit.ai" rel="noopener noreferrer"&gt;Code Rabbit&lt;/a&gt;, and &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt;—to supercharge your coding workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Cursor and Cloud Code excel for different personalities—Cursor for leaders, Cloud Code for craftspeople. Setting team-wide Cursor rules keeps best practices consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 2: Using AI Tools to Boost Engineering Excellence
&lt;/h3&gt;

&lt;p&gt;Apply AI directly to accelerate the four classic pillars.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Testing &amp;amp; Coverage&lt;/strong&gt; (e.g., auto-generating tests)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Pipelines&lt;/strong&gt; (e.g., AI-powered CI/CD suggestions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modularity &amp;amp; Code Review&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://coderabbit.ai" rel="noopener noreferrer"&gt;Code Rabbit&lt;/a&gt;: Cuts review time on pull requests, boosting speed.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.axle.ai/" rel="noopener noreferrer"&gt;Axel AI&lt;/a&gt;: Embeds in legacy code to help modernize architecture.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://antithesis.com" rel="noopener noreferrer"&gt;Antithesis&lt;/a&gt;: Runs containers to catch edge-case bugs in staging.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“Anything that can accelerate engineering excellence lights up my eyes.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Level 3: Incorporating AI Directly Into Product Features
&lt;/h3&gt;

&lt;p&gt;This is the “cool stuff”—voice agents, automated support, and smarter applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But beware:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Before over-engineering with tools like &lt;a href="https://www.langchain.com/" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt; and fancy agents, start simple. OpenAI API calls often get the job done. As you get closer to product market fit, start worrying about &lt;em&gt;human evals&lt;/em&gt;, prompt tuning, and security concerns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro move:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Start with &lt;em&gt;human-in-the-loop&lt;/em&gt;. Fully automated AI features rarely work perfectly from Day 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Distributed Teams: How GenAI Changes Remote Collaboration
&lt;/h2&gt;

&lt;p&gt;If your team is spread around the world—Eastern Europe, Latin America, Hong Kong—you know communication and documentation aren’t easy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GenAI is a game-changer for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Communication:&lt;/strong&gt; Coaching team members to use GenAI for clear, culturally-appropriate communication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; Auto-generating code and onboarding docs that are actually useful.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“With proper documentation and plan, new engineers can be effective in two weeks—if not one.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Challenge your team:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
No more 90-day onboarding. With GenAI-assisted docs, you can cut that down to 1-2 weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Use Case: devIQ—Bridging Technical and Non-Technical Teams
&lt;/h2&gt;

&lt;p&gt;Balki’s tool, &lt;a href="https://www.deviq.io/" rel="noopener noreferrer"&gt;devIQ&lt;/a&gt; (try it for free!), was born from a common startup pain: the disconnect between technical and non-technical staff.&lt;/p&gt;

&lt;h3&gt;
  
  
  How devIQ Helps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assesses engineering teams:&lt;/strong&gt; Across Balki’s five pillars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Translates complexity:&lt;/strong&gt; Makes technical progress educational for CEOs and business leads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gives grades and actionable steps:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;“Your grade is C in automated testing, B in GenAI fluency.”&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Offers prescriptive paths:&lt;/strong&gt; Specific ideas to improve grades&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use-case:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When Balki drops into an engagement, devIQ helps quickly pinpoint engineering gaps and opens authentic conversation between product and engineering.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If you methodically invest in the right pillars, your org will be 95th percentile or better—no matter your product.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Practical Tips for Staying Current in GenAI Engineering
&lt;/h2&gt;

&lt;p&gt;Let’s face it—AI moves &lt;em&gt;insanely&lt;/em&gt; fast. It’s easy to feel lost, overwhelmed, or permanently behind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Balki’s Learning Strategy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Focus 80% on problems inside your organization.&lt;/strong&gt;
Go out and find solutions that fit your actual engineering needs (e.g., legacy code modernization, engineering excellence pillars).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spend 20% dabbling in shiny new things.&lt;/strong&gt;
Keeps your creative juices flowing and occasionally unlocks breakthrough opportunities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Discipline matters.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Without intentional focus, you’ll spend all your time chasing distractions.&lt;/p&gt;

&lt;h2&gt;
  
  
  “Will AI Replace Us?”: The Real Question to Ask Before Adding GenAI
&lt;/h2&gt;

&lt;p&gt;This is the million-dollar question—and it’s not theoretical. Before shoving AI into your product, be honest:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is this something the customers want, and does it make their lives better by using GenAI inside the tool?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don’t waste time making your prompts perfect or optimizing the next toolchain before confirming user demand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro advice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insert a &lt;em&gt;human eval&lt;/em&gt; into early prototypes.&lt;/li&gt;
&lt;li&gt;Gradually replace manual involvement as the product matures.&lt;/li&gt;
&lt;li&gt;Automation isn’t instant—chip away bit by bit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future: Next-Level Tools and “The Stone Age to Modern Age” Shift
&lt;/h2&gt;

&lt;p&gt;AI moves at a ridiculous pace. Here’s what’s coming—and why you should care.&lt;/p&gt;

&lt;h3&gt;
  
  
  For New Engineers
&lt;/h3&gt;

&lt;p&gt;Starting today is easier than ever—you’re entering the AI-native world. But those legacy problems will catch up eventually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Team Resilience: Don’t Go It Alone
&lt;/h2&gt;

&lt;p&gt;Here’s a simple tip: get out of your shell. Connect with peer groups, ask for feedback, and share what you’re planning.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“When I see a new tool, I don’t jump in right away. I bring it to my cohorts for feedback, and I shave off weeks and hundreds of hours of research.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You get richer, higher quality feedback by collaborating—AI or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary: Key Takeaways for GenAI Engineers
&lt;/h2&gt;

&lt;p&gt;Let’s wrap it all up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GenAI &lt;strong&gt;has transformed engineering&lt;/strong&gt;—rapid POCs, scalable products, and changed job roles.&lt;/li&gt;
&lt;li&gt;“Engineering excellence” depends on five pillars, with GenAI fluency now essential.&lt;/li&gt;
&lt;li&gt;Don’t specialize too narrowly—full-stack, founder mindset is becoming the norm.&lt;/li&gt;
&lt;li&gt;Use AI for &lt;em&gt;real&lt;/em&gt; productivity: code review, documentation, collaboration, and direct product features.&lt;/li&gt;
&lt;li&gt;Start simple—and always validate with customer demands before ramping up automation.&lt;/li&gt;
&lt;li&gt;Leverage frameworks like devIQ to bridge business/engineering gaps and accelerate progress.&lt;/li&gt;
&lt;li&gt;Stay disciplined in your learning, and seek feedback from peers to keep your engineering sharp.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>podcast</category>
    </item>
    <item>
      <title>How OAuth, MCP, and the OpenAI Apps SDK, Power the Next Generation of Interactive AI Experiences (with Stytch &amp; OpenAI)</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Tue, 04 Nov 2025 20:08:17 +0000</pubDate>
      <link>https://dev.to/codingcatdev/how-oauth-mcp-and-the-openai-apps-sdk-power-the-next-generation-of-interactive-ai-experiences-1agm</link>
      <guid>https://dev.to/codingcatdev/how-oauth-mcp-and-the-openai-apps-sdk-power-the-next-generation-of-interactive-ai-experiences-1agm</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/podcast/how-oauth-mcp-and-the-openai-apps-sdk-power-the-next-generation-of-interactive-ai-experiences" rel="noopener noreferrer"&gt;https://codingcat.dev/podcast/how-oauth-mcp-and-the-openai-apps-sdk-power-the-next-generation-of-interactive-ai-experiences&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt;Ever feel like user authentication is one hot mess of protocols, random forms, and endless “Sign in with Google” buttons? Or maybe you’ve heard rumblings about “OAuth” and “MCP servers” but wondered how they actually fit into the web (and now, AI) landscape? Well, you’re in the right place!&lt;/p&gt;

&lt;p&gt;In this deep dive, I sit down with Max from Stytch, now part of Twilio!, to break down everything you’ve ever wanted to know about OAuth, why it matters, and how it’s suddenly become crucial for connecting Large Language Models (LLMs) and agents to external services in a secure, user-friendly way. Plus, we’ll get under the hood of the coolest Tamagotchi-inspired AI app, &lt;a href="https://github.com/stytchauth/chatagotchi" rel="noopener noreferrer"&gt;Chatagotchi&lt;/a&gt;, built using OpenAI’s Apps SDK and MCP.&lt;/p&gt;

&lt;p&gt;By the end of this post, you’ll:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Know what OAuth, MCP, and the Apps SDK are and why they’re key for AI integrations&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;See a real-world &lt;a href="https://github.com/stytchauth/chatagotchi" rel="noopener noreferrer"&gt;Chatagotchi&lt;/a&gt; demo and learn how it works&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Understand why authentication flows matter—especially when security is at stake&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Get actionable insights for building your own secure, interactive AI-powered apps&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ready to level up your understanding? Let’s jump in!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Stytch &amp;amp; Why Authentication Is So Hard
&lt;/h2&gt;

&lt;p&gt;Let’s kick things off with a little background. &lt;a href="https://stytch.com/" rel="noopener noreferrer"&gt;Stytch&lt;/a&gt; (now acquired by &lt;a href="https://www.twilio.com/" rel="noopener noreferrer"&gt;Twilio&lt;/a&gt;) is one of those rare companies laser-focused on making authentication simpler—think passwords, magic links, Face ID, social logins, and all the enterprise protocols (“SAML,” “OpenID”), often in places you wouldn’t even notice.&lt;/p&gt;

&lt;p&gt;When I asked Max, product engineer at Stytch, about the job, his answer was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"We take all of that data and we build tools that help developers manage that so you don't have to worry about building your own sign in form."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Stytch spent their early years helping developers &lt;strong&gt;pull user data in securely&lt;/strong&gt;, but over the past year, their focus has flipped to &lt;strong&gt;pushing user data out to other systems&lt;/strong&gt;—the critical piece for modern integrations, cross-app experiences, and now, AI agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Is Authentication So Crazy Complicated?
&lt;/h3&gt;

&lt;p&gt;Here’s the fun part: Picking &lt;em&gt;just&lt;/em&gt; authentication with passwords is &lt;em&gt;easy-ish&lt;/em&gt; if you’re careful with things like hashing. But add multi-factor authentication (MFA), social logins, SAML, OTP, magic links, mobile integrations, and you’re suddenly looking at months of build-out and endless docs.&lt;/p&gt;

&lt;p&gt;Max summed it up hilariously:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"You can build a simple login form in an afternoon. You can build like full consumer identity, access management in a lifetime."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And if you’re wondering, “Why not just roll my own?”, you’re not alone. But trust me, it’s a lot of work—unless you tap into an expert solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking Down OAuth—More Than Just a “Login with Google” Button
&lt;/h2&gt;

&lt;p&gt;Alright, so what &lt;em&gt;is&lt;/em&gt; OAuth? If you’ve ever clicked “Login with Google” (or Facebook, or Microsoft), you’re using OAuth under the hood.&lt;/p&gt;

&lt;p&gt;But OAuth is &lt;em&gt;not&lt;/em&gt; just a protocol—it’s a &lt;strong&gt;collection of more than 40 RFCs (tech specs)&lt;/strong&gt; developed and refined by thousands of security experts and companies like &lt;a href="https://www.ietf.org/" rel="noopener noreferrer"&gt;IETF&lt;/a&gt; and the &lt;a href="https://openid.net/foundation/" rel="noopener noreferrer"&gt;OpenID Foundation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s why that matters: OAuth lets you &lt;strong&gt;securely share user data from one place to another&lt;/strong&gt;—from web apps to desktop clients, mobile apps, even smart TVs—and every step is designed to keep the user in control and the systems secure.&lt;/p&gt;

&lt;h3&gt;
  
  
  OAuth: The Three Key Pieces
&lt;/h3&gt;

&lt;p&gt;Let’s nerd out for a second. OAuth relies on three main parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Server / Identity Provider&lt;/strong&gt;
This is what &lt;em&gt;knows who you are&lt;/em&gt; (Netflix.com, accounts.google.com, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Server&lt;/strong&gt;
The API that actually &lt;em&gt;holds the data&lt;/em&gt; (the giant boxes with Netflix movies, your Google Drive).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt;
The “thing” (app, TV, desktop program) &lt;em&gt;trying to access the data&lt;/em&gt; on your behalf.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s how it fits together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client asks the authorization server, “Can I get access?”&lt;/li&gt;
&lt;li&gt;The authorization server gives the client an &lt;strong&gt;access token&lt;/strong&gt; if the user consents.&lt;/li&gt;
&lt;li&gt;The client hands the token to the resource server and gets the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Netflix Example
&lt;/h4&gt;

&lt;p&gt;Let’s say you want to watch Netflix on your smart TV:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Netflix.com is your &lt;strong&gt;authorization server&lt;/strong&gt; (handles login and your identity)&lt;/li&gt;
&lt;li&gt;Netflix’s servers with all the movies are the &lt;strong&gt;resource server&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Your smart TV is the &lt;strong&gt;client&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The flow ensures your TV only gets access to &lt;em&gt;watch movies&lt;/em&gt;—not, for example, to change your credit card!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It's really common to share your data from a website to a native app... even to devices like televisions. And OAuth is about how the user and the service provider work together to agree on how this data should be shared.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;A flow diagram showing OAuth authorization between TV, Netflix, and the servers&lt;/em&gt;---&lt;/p&gt;

&lt;h2&gt;
  
  
  OAuth in Action: Real-World Example
&lt;/h2&gt;

&lt;p&gt;Let's walk through a classic OAuth flow—the Authorization Code Flow—just like you’d see when logging in to a new app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;User tries to connect an app (e.g. smart TV to Netflix)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TV sends login request to the Authorization Server (Netflix.com)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User authenticates (maybe with password, Face ID, or magic link)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authorization server issues an access token to the TV&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TV now uses this token to fetch movie data and play content&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;OAuth doesn’t tell Netflix how to do its login (could be password, SAML, Face ID, etc.)—that’s left flexible so you can customize for your users.&lt;/p&gt;

&lt;p&gt;And that’s where &lt;strong&gt;Stytch&lt;/strong&gt; shines—helping you build flexible login flows so you don’t have to reinvent the wheel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Is OAuth So Important?
&lt;/h3&gt;

&lt;p&gt;Beyond “login with Google,” OAuth lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limit permissions to &lt;em&gt;just what’s needed&lt;/em&gt; (TV can’t change your billing info)&lt;/li&gt;
&lt;li&gt;Support &lt;em&gt;lots&lt;/em&gt; of login methods (Face ID, magic links, social sign-in, enterprise SSO)&lt;/li&gt;
&lt;li&gt;Enable secure integrations between systems&lt;/li&gt;
&lt;li&gt;Trust that the protocols have been tested for years by security experts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How OAuth Powers MCP (Model Context Protocol) for AI Agents
&lt;/h2&gt;

&lt;p&gt;So what does all this have to do with AI agents, LLMs (like &lt;a href="https://chat.openai.com/" rel="noopener noreferrer"&gt;ChatGPT&lt;/a&gt;), and the hot new ecosystem of “apps” running on top of them?&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter MCP: The “Plug-and-Play” Data Ecosystem for LLMs and AI Agents
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; is trying to standardize how AI agents and LLMs (think ChatGPT, Claude, Gemini) talk to external sources—whether that’s your files, Google Drive, GitHub, Slack, or a custom backend.&lt;/p&gt;

&lt;p&gt;Instead of writing custom code for every connector, MCP aims to be a &lt;strong&gt;unified protocol&lt;/strong&gt; so agents and data sources can connect with minimal fuss.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If you wanted to build an educational service using MCP and roll it out to a high school... are you going to give every student their own API key? I just don't see it going well.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s where OAuth comes in—&lt;strong&gt;making these flows secure and approachable for users&lt;/strong&gt;, versus requiring every person to find and store their own API keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typical MCP Architecture Using OAuth:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP Clients&lt;/strong&gt; (like ChatGPT, Claude): want to access external data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Servers&lt;/strong&gt;: host the data, are “resource servers” in OAuth terms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Server&lt;/strong&gt;: handles identity (as in “who’s asking?”)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAuth&lt;/strong&gt;: bridges the gap, so the MCP client gets a token and can do stuff &lt;em&gt;only&lt;/em&gt; the user has approved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design means users &lt;em&gt;never see an API key&lt;/em&gt; and MCP servers don’t directly handle logins—they just rely on the secure flow provided by OAuth.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A diagram showing MCP clients, servers, Authorization Server, and OAuth tokens flowing between them&lt;/em&gt;---&lt;/p&gt;

&lt;h2&gt;
  
  
  Local vs Remote MCP Servers—And Why OAuth Wins
&lt;/h2&gt;

&lt;p&gt;Now things get spicy: When you’re building out MCP connectors, you’ll deal with &lt;strong&gt;local&lt;/strong&gt; (on your machine) vs &lt;strong&gt;remote&lt;/strong&gt; (on the cloud) MCP servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local MCP Servers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Great for editing code, local files, or pictures&lt;/li&gt;
&lt;li&gt;Doesn’t make sense for mass-market products (people don’t want to install/maintain software, security hassles)&lt;/li&gt;
&lt;li&gt;Okay for developer tools, not for mainstream commercial apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Remote MCP Servers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Typical web APIs, running in the cloud&lt;/li&gt;
&lt;li&gt;Easier for everyone to access, since no installing of local software&lt;/li&gt;
&lt;li&gt;Often rely on API Keys - not ideal for mass-market apps (most people don’t know how to manage API keys or environment variables)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;OAuth is a familiar and user-friendly solution.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Most people have gone through OAuth flows (“Sign in with Google/Facebook”)&lt;/li&gt;
&lt;li&gt;Removes the need for users to wrangle technical setup&lt;/li&gt;
&lt;li&gt;Widely adopted and secure&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“OAuth is something that all of us do every day, multiple times a day... and you don't need to be technical in order to take advantage of it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Chatagotchi: Building a Tamagotchi-Inspired App with MCP and OAuth
&lt;/h2&gt;

&lt;p&gt;Now for the fun part! Max built a &lt;strong&gt;Chatagotchi app&lt;/strong&gt;—basically Tamagotchi for modern AI chat—using the OpenAI Apps SDK and MCP protocol, all securely wired up with OAuth.&lt;/p&gt;

&lt;p&gt;Let’s break down how it all fits together.&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%2F5mwde8r27bof3m91ls5i.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%2F5mwde8r27bof3m91ls5i.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Setting Up Your App in ChatGPT
&lt;/h3&gt;

&lt;p&gt;You start off by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running an MCP server (the backend for Chatagotchi)&lt;/li&gt;
&lt;li&gt;Going to ChatGPT → Settings → Apps and Connectors → Advanced Settings → Developer Mode&lt;/li&gt;
&lt;li&gt;Hitting “Create” to add your app

&lt;ul&gt;
&lt;li&gt;Specify name, description, MCP server URL&lt;/li&gt;
&lt;li&gt;See a list of available tools (Start game, Feed pet, Play with pet, List achievements)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: OAuth Flow in Action
&lt;/h3&gt;

&lt;p&gt;To keep everything secure and remember who you are, you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hit Connect&lt;/strong&gt; inside ChatGPT, triggering an OAuth flow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log in via Google&lt;/strong&gt; (with Stytch handling the backend)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review OAuth consent screen&lt;/strong&gt;, authorizing ChatGPT to:

&lt;ul&gt;
&lt;li&gt;Start a new game, feed your pet, play with pet, list achievements&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;“So Stytch was responsible... This is our drop-in SDK. This is a little React component and then a little bit about Stytch under the hood... You can use that to build whatever experience you want.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The cool part? The &lt;strong&gt;UI and consent screen are highly customizable&lt;/strong&gt;, letting you maintain your brand and user experience.&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%2Fqn5b8zi9wuhw7mvnn4iy.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%2Fqn5b8zi9wuhw7mvnn4iy.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OAuth consent screen inside ChatGPT displaying Stytch’s customized React&lt;/em&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Playing the Game and Handling Data
&lt;/h3&gt;

&lt;p&gt;With the app installed, you can chat with Chatagotchi inside ChatGPT. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask “What tools are available?”&lt;/li&gt;
&lt;li&gt;Start a new game (give your virtual pet a name—say, “AJ”)&lt;/li&gt;
&lt;li&gt;Feed your pet (“Pizza,” “Apple,” “Cookie,” etc.)&lt;/li&gt;
&lt;li&gt;ChatGPT inspects the MCP tool schema and provides valid options&lt;/li&gt;
&lt;li&gt;ChatGPT checks with you for permission to invoke each tool&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“ChatGPT understands the app and is kind of co-playing it with you. Like a Dungeons and Dragons Dungeon Master experience, almost.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  All UI interactions, loading screens, and game state are handled by:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;MCP server returning JSON data and dynamic HTML for widget rendering&lt;/li&gt;
&lt;li&gt;ChatGPT rendering widgets in iframes, powered by your custom React micro-frontends&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Inside the Code: MCP Server, OAuth, and Widget Rendering
&lt;/h2&gt;

&lt;p&gt;Okay, let’s get nerdy! Here’s how the MCP tools, OAuth, and output templates work in the actual code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining MCP Tools with TypeScript SDK
&lt;/h3&gt;

&lt;p&gt;Max uses the official &lt;a href="https://github.com/model-context-protocol/mcp-ts" rel="noopener noreferrer"&gt;MCP TypeScript SDK&lt;/a&gt; to define tools—simple, readable, and powerful.&lt;/p&gt;

&lt;p&gt;Here’s a snippet for how you’d define the New Game tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new-game&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Start New Game&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Creates a new Chatagotchi pet.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;_meta&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;openai/outputTemplate&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;ui://widget/pet.html&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;openai/toolInvocation/invoking&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;Waking up your new pet&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;openai/toolInvocation/invoked&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;Say hello to your new pet!&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;openai/widgetAccessible&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="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="na"&gt;petName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name your pet&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="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;petName&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="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;authInfo&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What does this do?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Defines the schema&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Specifies input requirements&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Links to an output template (pet.html) for UI rendering&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Includes metadata for special UI handling in OpenAI&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;The tool is registered with the MCP server, so ChatGPT knows its functionality and what data it expects. The metadata allows custom messages and UI rendering to keep the experience engaging and aligned with your brand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic UI, Output Templates, and Security Insights
&lt;/h3&gt;

&lt;p&gt;Each tool can return custom HTML/JS to render beautiful widgets directly inside ChatGPT chats. Here’s the basic structure for an output template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- pet.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"pet-widget"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://your-domain.com/pet.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pet.js&lt;/code&gt; grabs the JSON result (the “structured content”), renders the pet state with React/Vue/vanilla JS—whatever you prefer.&lt;/p&gt;

&lt;h4&gt;
  
  
  How Does ChatGPT Render Widgets?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Grabs the output template (“pet.html”) from your server&lt;/li&gt;
&lt;li&gt;Loads its contents into an &lt;strong&gt;iframe&lt;/strong&gt;, sandboxed for security&lt;/li&gt;
&lt;li&gt;Runs your bundled JS code to display the tool call details (passed into the iframe via the &lt;code&gt;window.openai&lt;/code&gt; global) as structured HTML to the user&lt;/li&gt;
&lt;li&gt;Keeps everything isolated, so you can use whatever UI stack you want
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function App() {
  const input = useOpenAiGlobal('toolInput');
  const output = useOpenAiGlobal('toolInput');

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;Input:&amp;lt;/div&amp;gt;
      &amp;lt;pre&amp;gt;{JSON.stringify(input, null, 2)}&amp;lt;/pre&amp;gt;
      &amp;lt;div&amp;gt;Output:&amp;lt;/div&amp;gt;
      &amp;lt;pre&amp;gt;{JSON.stringify(output, null, 2)}&amp;lt;/pre&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

createRoot(document.getElementById('pet-root')!).render(&amp;lt;App /&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;“There's been a lot of work... around iframes since Yahoo days... Now we found out how bad iframes were. Oh, well, don't say that, because this is all iframes too. We'll see how much trouble they cause, but hopefully they stay.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Security Notes
&lt;/h3&gt;

&lt;p&gt;OpenAI is locking things down—once a tool or app is published, names, signatures, descriptions are locked. No sneaky changes!&lt;/p&gt;

&lt;p&gt;If you try to roll out breaking changes or new behavior, you’ll need to resubmit for human review, keeping the ecosystem clean and secure for users.&lt;/p&gt;

&lt;p&gt;Also, there are considerations around referencing remote JS/CSS assets: Should your chats be deterministic (never changing), or flexible for updates? Expect best practices around static CDNs, asset hashes, and widget isolation to evolve as these ecosystems mature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security, User Experience, and What’s Next in AI App Distribution
&lt;/h2&gt;

&lt;p&gt;As cool as this all sounds, there are &lt;em&gt;big&lt;/em&gt; implications for security, user education, and app distribution.&lt;/p&gt;

&lt;h3&gt;
  
  
  OAuth Isn’t Optional—It’s Essential
&lt;/h3&gt;

&lt;p&gt;Whether you’re dealing with students, mass-market users, or enterprise customers, asking them to manage API keys is dead on arrival. OAuth flows are familiar and easy, allowing anyone to connect apps without technical frustration.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Bots and App Stores—The New OS?
&lt;/h3&gt;

&lt;p&gt;ChatGPT and similar platforms are turning into new “Operating Systems” for interacting with external services—much like how the Apple App Store changed mobile distribution.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is ChatGPT an app? Is ChatGPT an operating system or a runtime?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;_Mockup of ChatGPT with a side bar of installed apps, resembling an app store experience_We’re already seeing the beginnings of an “App Store” for AI agents and plugins—apps compete for distribution, brand engagement, and new discovery.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer Experience
&lt;/h3&gt;

&lt;p&gt;For developers, it’s shockingly easy to get started if you understand web fundamentals and a little OAuth. MCP’s TypeScript SDK, Apps SDK documentation, and Stytch’s drop-in APIs are accessible, flexible, and well-supported.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I was very surprised by how easy it was to get set up. There's a little bit of a learning curve and a mental curve around the RPC model... but it's not hard to think about—just a little different from classic web dev.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion &amp;amp; Key Takeaways
&lt;/h2&gt;

&lt;p&gt;Let’s sum it all up! Here’s what you should remember from this deep dive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OAuth is everywhere&lt;/strong&gt;—It’s how most users expect to authenticate and share access, and it’s critical for both web and AI agent integrations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt; is the key bridge for enabling LLMs and agents to talk to external data sources and tools, safely and flexibly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote MCP servers + OAuth is the right combo&lt;/strong&gt; for mainstream, user-friendly integrations (not API keys!)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apps SDK is turning ChatGPT into a new “App Store”—with custom micro-frontends powered by widgets&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building these integrations isn’t rocket science&lt;/strong&gt;—once you grasp the OAuth flow, MCP protocol, and widget architecture, you’re off to the races&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and user experience are top priorities&lt;/strong&gt;—expect standards to keep evolving, but OAuth’s staying power is guaranteed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open standards (like MCP)&lt;/strong&gt; mean your integrations can work across many platforms, not just closed ecosystems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What Do You Think?
&lt;/h3&gt;

&lt;p&gt;Have you built an MCP server or a ChatGPT app? What’s your biggest hang-up with OAuth flows or widget rendering? Are you excited about the future of “app stores” for AI agents—or maybe a little worried?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drop a comment below—we love hearing what fellow developers, educators, and curious minds think!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to Learn More?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Watch the full video with Stytch’s Max and CodingCat.dev&lt;/strong&gt; on YouTube:
&lt;a href="https://youtu.be/w0eZQm0O_h8" rel="noopener noreferrer"&gt;OpenAI Apps SDK Video&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dive deeper into official docs:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stytch.com/docs" rel="noopener noreferrer"&gt;Stytch Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://oauth.net/2/" rel="noopener noreferrer"&gt;OAuth 2.0 Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://platform.openai.com/docs/overview" rel="noopener noreferrer"&gt;OpenAI Apps SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.org/" rel="noopener noreferrer"&gt;Model Context Protocol (MCP)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;And of course—&lt;strong&gt;subscribe to &lt;a href="https://www.youtube.com/codingcatdev?sub_confirmation=1" rel="noopener noreferrer"&gt;CodingCat.dev on YouTube&lt;/a&gt;&lt;/strong&gt; for more in-depth interviews, walkthroughs, and tutorials!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If you maintain a web presence and care about Google search and reaching customers, ChatGPT is a new distribution mechanism. Even if it’s not ChatGPT, something else will take its place, and OAuth will always be in the mix.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks again to Max from Stytch for breaking down the intersecting worlds of OAuth, MCP, and AI agent apps. Can’t wait to see what you build next!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Max’s Chatagotchi widget in action inside ChatGPT, showing custom UI, game state, and seamless OAuth flow&lt;/em&gt;---&lt;/p&gt;

&lt;p&gt;Got questions? Post them below, and we’ll dive in together. Happy coding, perfect peeps! 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>podcast</category>
    </item>
    <item>
      <title>Firebase SQL with Data Connect</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Tue, 28 Oct 2025 17:56:51 +0000</pubDate>
      <link>https://dev.to/codingcatdev/firebase-sql-with-data-connect-3i1k</link>
      <guid>https://dev.to/codingcatdev/firebase-sql-with-data-connect-3i1k</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/podcast/firebase-sql-with-data-connect" rel="noopener noreferrer"&gt;https://codingcat.dev/podcast/firebase-sql-with-data-connect&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction: Why Do We Need Firebase Data Connect?
&lt;/h2&gt;

&lt;p&gt;Let’s be real: Firebase has been a go-to for fast app launches for years, but what happens when your app's logic gets complex, your data relationships grow hairy, or you want join-heavy reports, analytics, and powerful search? Google heard the pain points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“I need relational queries and joins.”&lt;/li&gt;
&lt;li&gt;“Can I finally use full text search, not just basic keyword matching?”&lt;/li&gt;
&lt;li&gt;“Can my AI agents interact with my database, securely and conveniently?”&lt;/li&gt;
&lt;li&gt;“Can I swap between secure APIs and developer-friendly tools on the fly?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’re not alone. That’s exactly why Firebase Data Connect was born.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this article, you’ll understand:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Data Connect blends SQL (PostgreSQL) power with Firebase’s cloud-native ease.&lt;/li&gt;
&lt;li&gt;Where it beats Firestore—and when you should stick with Firestore instead.&lt;/li&gt;
&lt;li&gt;How to build secure APIs, type-safe SDKs, and connect your data to AI agents like Gemini.&lt;/li&gt;
&lt;li&gt;How to use full text search and vector search (semantic matching) like a pro.&lt;/li&gt;
&lt;li&gt;Practical steps to get started—even locally with emulators!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Meet Tyler Crowe &amp;amp; The Birth of Data Connect
&lt;/h2&gt;

&lt;p&gt;Tyler Crowe isn’t just a Firebase PM—he’s been the brains behind Firebase Auth, AppCheck, and now Data Connect. In our &lt;a href="https://www.youtube.com/playlist?list=PLUKgAjyG9B0ZhUEXp9eVa7h4L__FDW3uV" rel="noopener noreferrer"&gt;season 5 podcast&lt;/a&gt;, Tyler explained:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We built Data Connect under a single premise. You write the query, we do the rest."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The real motivation? Thousands of developers pining for the best of both worlds: Firebase’s developer joy… plus the relational might of SQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to go deeper into Tyler's journey? &lt;a href="https://youtu.be/N25khadfUag" rel="noopener noreferrer"&gt;Listen to the full podcast episode&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Firebase Data Connect?
&lt;/h2&gt;

&lt;p&gt;In a nutshell: &lt;strong&gt;Data Connect is a fully managed, cloud-native SQL database service—built on &lt;a href="https://cloud.google.com/sql" rel="noopener noreferrer"&gt;Cloud SQL&lt;/a&gt; (hello, PostgreSQL!)—and deeply integrated into &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’ve ever wrangled cloud infrastructure, worried about scaling, or cursed at manual security configs, Data Connect is your new best friend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is Data Connect Important?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relational Power&lt;/strong&gt;: Complex queries, joins, and analytics—finally possible!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Infrastructure Headaches&lt;/strong&gt;: Just click, deploy, and go. You never touch a server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure by Design&lt;/strong&gt;: Auth, AppCheck, and access directives built in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-Ready&lt;/strong&gt;: Schema and queries can be generated by AI agents like &lt;a href="https://ai.google.com/gemini/" rel="noopener noreferrer"&gt;Gemini&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future Proof&lt;/strong&gt;: Roadmap includes support for other data sources beyond Cloud SQL.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Highlights
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built on &lt;a href="https://cloud.google.com/sql" rel="noopener noreferrer"&gt;Cloud SQL PostgreSQL&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-Safe SDKs&lt;/strong&gt; auto-generated for &lt;a href="https://developer.android.com/" rel="noopener noreferrer"&gt;Android&lt;/a&gt;, &lt;a href="https://developer.apple.com/" rel="noopener noreferrer"&gt;iOS&lt;/a&gt;, and web&lt;/li&gt;
&lt;li&gt;Integrated with &lt;a href="https://firebase.google.com/docs/auth" rel="noopener noreferrer"&gt;Firebase Auth&lt;/a&gt; and &lt;a href="https://firebase.google.com/docs/app-check" rel="noopener noreferrer"&gt;AppCheck&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Out-of-the-box support for &lt;strong&gt;Full Text Search&lt;/strong&gt; and &lt;strong&gt;Vector Search&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Agentic workflows for AI agents and smart queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Want a more hands-on intro? &lt;a href="https://youtube.com/shorts/xA3J_Q4cdYY?feature=share" rel="noopener noreferrer"&gt;Check out our beginner’s guide to Firebase&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Connect vs Firestore: The Relational Revolution
&lt;/h2&gt;

&lt;p&gt;Let’s break down a classic developer question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Should I stick with Firestore, or do I need Data Connect?”&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;&lt;strong&gt;Firestore&lt;/strong&gt; (or the classic Realtime Database) was built for real-time sync, offline-first experiences, and mobile scale. &lt;strong&gt;But…&lt;/strong&gt; when your data needs get complex—think relational joins, analytics, extensions—Firestore just isn’t enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Connect Brings You:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ease of Firebase SDKs&lt;/li&gt;
&lt;li&gt;Pure SQL power (JOINs, aggregation, constraints)&lt;/li&gt;
&lt;li&gt;Deep API and security control&lt;/li&gt;
&lt;li&gt;Analytics and full text search at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Firestore&lt;/strong&gt; is still perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time sync&lt;/li&gt;
&lt;li&gt;Offline-first mobile apps&lt;/li&gt;
&lt;li&gt;Simple, single-table queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not sure which is best for you? &lt;a href="https://codingcat.dev/post/firebase-firestore-vs-data-connect-unlocking-your-data-s-full-potential" rel="noopener noreferrer"&gt;Check out our full breakdown: Data Connect vs Firestore&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Type-Safe SDKs and Secure API Endpoints
&lt;/h2&gt;

&lt;p&gt;Here’s the developer dream: define a query, get a &lt;strong&gt;secure API endpoint&lt;/strong&gt;—and a fully typed SDK that plugs right into your frontend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Is Type Safety So Powerful?
&lt;/h3&gt;

&lt;p&gt;Type-safe SDKs cut debugging hassles, let your IDE catch mistakes before runtime, and speed up development with auto-completion.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Data Connect Does It
&lt;/h3&gt;

&lt;p&gt;When you save a query/mutation, Data Connect generates an SDK for your chosen platform. That SDK ensures type safety, authentication, and converts your calls into secure, backend-executed SQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Querying Movie Reviews in TypeScript&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;queryReviewsForMovie&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./sdk/movieReviews&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;reviews&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;queryReviewsForMovie&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;movieID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MOVIE123&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;This fetches reviews securely, using the backend’s query definition and type validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Agents &amp;amp; Schema Generation with Gemini
&lt;/h2&gt;

&lt;p&gt;Here’s one for the future: &lt;strong&gt;Let AI design your database.&lt;/strong&gt; With &lt;a href="https://ai.google.com/gemini/" rel="noopener noreferrer"&gt;Gemini&lt;/a&gt;, Data Connect enables schema and query generation straight from natural language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Does This Matter?
&lt;/h3&gt;

&lt;p&gt;Instead of fiddling with table structures, just describe your app in plain English and watch Gemini build a solid schema—saving you hours.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Describe Your App&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"I need a movie review app with reviews, movies, actors, and users."&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini Generates SQL&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Movies&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fill&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;table&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uuidV4()&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="na"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="na"&gt;releaseYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;
  &lt;span class="na"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
  &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Float&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="nx"&gt;Metadata&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;MovieMetadata&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;one&lt;/span&gt; &lt;span class="nx"&gt;relationship&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fill&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;MovieMetadata&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MovieMetadata&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;table&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt; &lt;span class="nx"&gt;creates&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="nf"&gt;table &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MovieMetadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;It&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;reference&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;holds&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;primary&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;referenced&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;In&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;movieId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;references&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;implied&lt;/span&gt;
  &lt;span class="na"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="na"&gt;movieId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;above&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt;
  &lt;span class="na"&gt;director&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Actors&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Suppose&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;actor&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;participate&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;multiple&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;have&lt;/span&gt; &lt;span class="nx"&gt;multiple&lt;/span&gt; &lt;span class="nx"&gt;actors&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Actors &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;vice&lt;/span&gt; &lt;span class="nx"&gt;versa&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;relationship&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fill&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;Actor&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Actor&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;table&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="na"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;col&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;varchar(30)&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="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Join&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;relationship&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;actors&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;signifies&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;primary&lt;/span&gt; &lt;span class="nf"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;In&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;movieId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actorId&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;generated&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;reference&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fill&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;MovieActor&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MovieActor&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;table&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="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;movie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;actor&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="err"&gt;#&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt; &lt;span class="nx"&gt;creates&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="nf"&gt;table &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MovieActor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;holds&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;primary&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;referenced&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;In&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;implied&lt;/span&gt;
  &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;movieId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;implied&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;see&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;implicit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gql&lt;/span&gt;

  &lt;span class="nx"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Actor&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;actorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;implied&lt;/span&gt;  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;see&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;implicit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gql&lt;/span&gt;

  &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;supporting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Suppose&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;leave&lt;/span&gt; &lt;span class="nx"&gt;reviews&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;reviews&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;reviews&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;relationship&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;relationship&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fill&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;table&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;col&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth_uid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;col&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;dataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;varchar(50)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;generated&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;Review&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;reviews_on_user&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;movies_via_Review&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Join&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;many&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;many&lt;/span&gt; &lt;span class="nx"&gt;relationship&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;favorite&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fill&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;FavoriteMovie&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FavoriteMovie&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FavoriteMovies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;singular&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;favorite_movie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;plural&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;favorite_movies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;movie&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="err"&gt;#&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ref&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;implicit&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Reviews&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fill&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;Review&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Review&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reviews&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;movie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&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="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uuidV4()&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;
  &lt;span class="nx"&gt;reviewText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
  &lt;span class="nx"&gt;reviewDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request.time&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tweak &amp;amp; Refine On the Fly&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Add constraints, relationships, or new features (“Let’s add a chat!”).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This isn’t just a parlor trick—&lt;strong&gt;schema quality is rock solid&lt;/strong&gt;. Want to try it? Play with Gemini in &lt;a href="https://codelabs.developers.google.com/gemini-cli-hands-on" rel="noopener noreferrer"&gt;this hands-on codelab&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Your First Data Connect App
&lt;/h2&gt;

&lt;p&gt;Let’s roll up our sleeves. Setting up Data Connect is designed to be painless.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Building Should Be Instant
&lt;/h3&gt;

&lt;p&gt;No one wants to spend hours on infrastructure just to test an idea. Data Connect delivers with fast onboarding, ephemeral databases for prototyping, and instant querying.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start a New Service in Studio&lt;/strong&gt;
Open &lt;a href="https://studio.firebase.google.com/" rel="noopener noreferrer"&gt;Firebase Studio&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design Schema with Gemini or Wizard&lt;/strong&gt;
Let Gemini handle heavy lifting, or design schema manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy to Cloud SQL&lt;/strong&gt;
Choose ephemeral (for prototyping) or persistent DB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seed &amp;amp; Query Instantly&lt;/strong&gt;
Input demo data, run live queries, modify as needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Get inspired by our &lt;a href="https://youtu.be/N25khadfUag" rel="noopener noreferrer"&gt;movie review app walkthrough&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Browsing Data: Table vs JSON Views
&lt;/h2&gt;

&lt;p&gt;Data Connect gives you &lt;strong&gt;classic SQL table views&lt;/strong&gt; and old-school JSON blobs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Table View:&lt;/strong&gt; Rows and columns (easy for relational reasoning)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON View:&lt;/strong&gt; Structured for mutation/debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Vector embeddings (for AI search) show as massive numeric fields—expand for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lightning-Fast Full Text Search
&lt;/h2&gt;

&lt;p&gt;Trust me, this feature is a game-changer. Powered by PostgreSQL, you can search text in ways that Firestore could only dream about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Full Text Search?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Users expect robust search (not just basic string matching)&lt;/li&gt;
&lt;li&gt;Multi-field queries (title + description, for example)&lt;/li&gt;
&lt;li&gt;Natural language and advanced operators (AND, OR, NOT)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to Enable Full Text Search
&lt;/h3&gt;

&lt;p&gt;Annotate fields in your schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;searchable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;searchable&lt;/span&gt;&lt;span class="p"&gt;,...}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then craft your query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;searchMovies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;movies_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="n"&gt;MovieOverview&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Modes
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Plain:&lt;/strong&gt; General terms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phrase:&lt;/strong&gt; Exact phrase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query:&lt;/strong&gt; Operators for advanced search (&lt;code&gt;love -potion&lt;/code&gt; gets results with “love” but not “potion”)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Check out &lt;a href="https://firebase.google.com/docs/data-connect/solutions-full-text-search" rel="noopener noreferrer"&gt;how full text search works in detail&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Vector Search: Semantic Search for Real Apps
&lt;/h2&gt;

&lt;p&gt;Let’s take your search to the next level—&lt;strong&gt;semantic matching&lt;/strong&gt; with vector embeddings powered by &lt;a href="https://firebase.google.com/docs/data-connect/solutions-vector-similarity-search" rel="noopener noreferrer"&gt;Vertex AI&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Go Semantic?
&lt;/h3&gt;

&lt;p&gt;Full text search is great, but what if users type synonyms or phrases? Vector search returns results that &lt;em&gt;mean the same thing&lt;/em&gt;, not just match words.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Data (titles, descriptions) is fed to an embedding model (&lt;code&gt;text-embedding-gecko-005&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Embeddings live in a vector field (often 768 dimensions!)&lt;/li&gt;
&lt;li&gt;At query time, your search input is vectorized and compared for &lt;em&gt;cosine similarity&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example: Vector Search Query&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;searchMovies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;movies_vectorSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text-embedding-gecko-005"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;topK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;titledescriptionscore&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;This finds “Love Potion” when you search “Love Tonic”—because meaning matters!&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Queries &amp;amp; Mutations: Making Your API
&lt;/h2&gt;

&lt;p&gt;Here’s the “internals”: you define your queries and mutations (“operations”). Every operation is tracked with security, parameters, and API surface exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Add a Review Mutation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;addReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$movieId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$review&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;addReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movieId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$movieId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$review&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;idreview&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;This gives frontend devs type safety and full API clarity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generated SDKs: Streamlining Frontend Integration
&lt;/h2&gt;

&lt;p&gt;Once you’ve built your backend, integrating it is &lt;em&gt;instant&lt;/em&gt; just hit “Download SDK” and roll into any modern frontend. Or have it build out your own connector.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example using a React component&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initializeApp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getFirebaseConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./firebase-config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Your Firebase config&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SearchMovies&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@your-project-name/your-connector-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Generated SDK import&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MovieSearch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSearchTerm&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMovies&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getFirebaseConfig&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSearch&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="nc"&gt;SearchMovies&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nf"&gt;setMovies&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;movies_search&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error searching movies:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
        &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSearchTerm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search movies...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSearch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;movie&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="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;releaseYear&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;))}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Fully typed SDKs for React, Next.js, Vue, Angular, and more!&lt;/li&gt;
&lt;li&gt;AI agents (like Gemini) plug in seamlessly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security: Auth, Row-Level Access, and AppCheck
&lt;/h2&gt;

&lt;p&gt;Security isn’t just a checkbox—it’s &lt;strong&gt;part of every query and mutation&lt;/strong&gt; in Data Connect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Query-Level Security?
&lt;/h3&gt;

&lt;p&gt;Instead of hand-writing complex security rules at the collection/table level, Data Connect lets you lock down each operation directly.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@user&lt;/code&gt;: Requires authentication&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@public&lt;/code&gt;: Open access&lt;/li&gt;
&lt;li&gt;Expression-based (e.g. admin role, claims)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example: Secure Mutation Directive&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;addReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;@auth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;anonymous&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{...}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Row-level security: operations filter access using user IDs, roles, and more&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://firebase.google.com/docs/app-check" rel="noopener noreferrer"&gt;AppCheck&lt;/a&gt; compatibility—even for APIs like Stripe!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Local Development and Emulators
&lt;/h2&gt;

&lt;p&gt;Yes—you can develop and test everything locally!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Emulator spins up with PG Lite&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Seed and mutate data with demo apps in VS Code&lt;/li&gt;
&lt;li&gt;Test all queries, mutations, operations, &lt;em&gt;and&lt;/em&gt; security&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Start Data Connect emulator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase emulators:start &lt;span class="nt"&gt;--only&lt;/span&gt; data-connect

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  GraphQL Everywhere: Why It Matters
&lt;/h2&gt;

&lt;p&gt;It’s official: Data Connect’s API is &lt;strong&gt;GraphQL-powered&lt;/strong&gt;. Why should you care?&lt;/p&gt;

&lt;h3&gt;
  
  
  Why GraphQL?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ask for just what you need:&lt;/strong&gt; No overfetching or underfetching&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Joins, fragments, reusable types:&lt;/strong&gt; Compose powerful queries quickly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong types:&lt;/strong&gt; IDE/codegen support, easy refactoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security at query layer:&lt;/strong&gt; Fewer surprises&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example: Homepage Query With Fragments&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;homepage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;newReleases&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;MovieOverview&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="n"&gt;topMovies&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;MovieOverview&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="n"&gt;recentReviews&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;ReviewFragment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;MovieOverview&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;Learning curve? Sure! But flexibility and power make it worthwhile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Connect vs Firestore: How to Choose
&lt;/h2&gt;

&lt;p&gt;Here’s Tyler Crowe’s advice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If you need relational joins, heavy analytics, or want to use Postgres extensions—pick Data Connect.&lt;br&gt;&lt;br&gt;
If you need real-time sync, offline support, or fast mobile-first stuff, Firestore is your bread and butter.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Quick Guide
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Firestore:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time sync, offline support&lt;/li&gt;
&lt;li&gt;Massive scale&lt;/li&gt;
&lt;li&gt;Simple queries&lt;/li&gt;
&lt;li&gt;Mobile-first&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Connect:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex queries, analytics&lt;/li&gt;
&lt;li&gt;Relational schemas&lt;/li&gt;
&lt;li&gt;Joins/aggregations&lt;/li&gt;
&lt;li&gt;Full text &amp;amp; vector search&lt;/li&gt;
&lt;li&gt;Web or cross-platform workloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still unsure? &lt;strong&gt;Ask Gemini&lt;/strong&gt; right in Studio:&lt;br&gt;&lt;br&gt;
&lt;em&gt;"Should I use Data Connect or Firestore for my app?"&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next: Features Coming Soon
&lt;/h2&gt;

&lt;p&gt;The Data Connect team is just getting started. Look out for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RAW SQL queries (not just views!)&lt;/li&gt;
&lt;li&gt;More advanced backend caching/performance tuning&lt;/li&gt;
&lt;li&gt;Custom MCP server support for agentic workflows&lt;/li&gt;
&lt;li&gt;Multi-data source (not limited to Cloud SQL)&lt;/li&gt;
&lt;li&gt;Deeper AI integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stay updated via the &lt;a href="http://codingcat.dev/blog" rel="noopener noreferrer"&gt;CodingCat.dev blog&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion &amp;amp; Further Learning
&lt;/h2&gt;

&lt;p&gt;There’s never been a better time to be a Firebase developer. &lt;strong&gt;Data Connect bridges the world of enterprise-grade SQL and developer-friendly, cloud-native workflows.&lt;/strong&gt; Building secure apps, powerful queries, and integrating AI is finally within reach—whether you’re launching a startup or scaling to millions.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Data Connect brings SQL, security, and AI together in Firebase.&lt;/li&gt;
&lt;li&gt;You can use type-safe SDKs and GraphQL-powered APIs without fighting your infrastructure.&lt;/li&gt;
&lt;li&gt;Full text and vector search make your data "smarter" than ever.&lt;/li&gt;
&lt;li&gt;Security and access controls are baked in, not bolted on.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Subscribe
&lt;/h3&gt;

&lt;p&gt;🚀 &lt;strong&gt;Subscribe to &lt;a href="https://www.youtube.com/channel/UCnKZ8gEb78zXKMi1ns-IQ2g/join" rel="noopener noreferrer"&gt;youtube.com/codingcatdev&lt;/a&gt; for weekly web dev, Firebase, and AI content!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now, I’d love to hear from you:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;What would you build with Firebase Data Connect? What’s your dream feature or integration?&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Drop your ideas in the comments, tweet &lt;a href="https://twitter.com/CodingCatDev" rel="noopener noreferrer"&gt;@CodingCatDev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Happy codingcatting for perfect peeps ✨&lt;/p&gt;

&lt;h3&gt;
  
  
  Subscriptions
&lt;/h3&gt;

&lt;p&gt;Are you looking to boost your products reach? Have Alex create a video for you &lt;a href="https://codingcat.dev/sponsorships" rel="noopener noreferrer"&gt;https://codingcat.dev/sponsorships&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References &amp;amp; More Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://firebase.google.com/docs/data-connect" rel="noopener noreferrer"&gt;Firebase Data Connect Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/sql" rel="noopener noreferrer"&gt;Cloud SQL (Google)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/vertex-ai/docs/generative-ai/embeddings/get-text-embeddings" rel="noopener noreferrer"&gt;Vertex AI Embeddings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ai.google.com/gemini/" rel="noopener noreferrer"&gt;Gemini AI Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codingcat.dev/codelab/data-connect" rel="noopener noreferrer"&gt;Data Connect Codelabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/codingcatdev/firebase-data-connect-examples" rel="noopener noreferrer"&gt;Sample code and open source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://firebase.google.com/docs" rel="noopener noreferrer"&gt;Firebase Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codingcat.dev/blog" rel="noopener noreferrer"&gt;More web dev posts on CodingCat.dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
All code samples and workflows described here are for educational/demo purposes. Please consult the &lt;a href="https://firebase.google.com/docs" rel="noopener noreferrer"&gt;Firebase documentation&lt;/a&gt; for production best practices and latest updates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;This post is part of our deep dive series on Firebase. Major thanks to Tyler Crowe and the Google engineering team for moving web development into the AI-powered future!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>podcast</category>
    </item>
    <item>
      <title>Identity in AI Agents</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Fri, 24 Oct 2025 16:09:17 +0000</pubDate>
      <link>https://dev.to/codingcatdev/identity-in-ai-agents-1ipo</link>
      <guid>https://dev.to/codingcatdev/identity-in-ai-agents-1ipo</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/podcast/identity-access-management-for-agents-with-tobin-south" rel="noopener noreferrer"&gt;https://codingcat.dev/podcast/identity-access-management-for-agents-with-tobin-south&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt;Welcome back to CodingCat.dev! If you’ve ever found yourself neck-deep in the rabbit hole of identity, access management, and server security—especially in the brave new world of AI agents—today’s post is for you. I sat down with Dr. Tobin South, a security and AI expert, for a lively and insightful conversation that covers everything from fine-grained authentication and natural language access control (NLAC) to the nuances of Model Context Protocol (MCP) servers.&lt;/p&gt;

&lt;p&gt;Whether you’re building your own MCP server or just curious about how identity management is evolving in AI-driven environments, this post will break it all down in simple, practical terms. And of course, we’ll share tons of real-world lessons, tips, and code to keep you safe, sane, and ahead of the curve.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If you’re building an MCP server, you definitely need to check this out.” — Dr. Tobin South&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction: The Identity Management Problem in AI Agents
&lt;/h2&gt;

&lt;p&gt;Have you ever handed over your admin credentials to an AI agent and prayed it wouldn’t accidentally nuke your production server? No? Just me? Well, as AI transforms the way we interact with infrastructure, applications, and even our inboxes, old-school identity and access management (IAM) tools are getting stretched to the limit.&lt;/p&gt;

&lt;p&gt;In today's post, we’ll dig into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What fine-grained authentication looks like when AI agents drive the bus.&lt;/li&gt;
&lt;li&gt;How emerging protocols like MCP are reshaping best practices.&lt;/li&gt;
&lt;li&gt;The new problems (and hilariously dangerous pitfalls) you’ll encounter when serving up APIs for chatbots and generative models.&lt;/li&gt;
&lt;li&gt;Practical, real-world steps for building a secure MCP server today.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of this post, you’ll have actionable advice on securing your MCP servers, managing agentic identities, and setting sane, practical access control—whether you’re at a startup or shipping software at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet Dr. Tobin South: AI, Security, and the Academic Hustle
&lt;/h2&gt;

&lt;p&gt;Dr. Tobin South is no stranger to the overlapping worlds of AI research, security, and enterprise software. After a wild ride through MIT’s AI scene (and a ChatGPT moment that changed everything), Tobin plunged into the depths of security—eventually landing at &lt;a href="https://workos.com" rel="noopener noreferrer"&gt;WorkOS&lt;/a&gt;, where he leads AI agent security, building MCP and IAM tooling for the world’s biggest AI labs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I spent a bunch of years thinking deeply about what AI security means... and there are really unique security challenges for agents.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tobin also runs a research lab at Stanford in partnership with &lt;a href="https://www.consumerreports.org/" rel="noopener noreferrer"&gt;Consumer Reports&lt;/a&gt;, focusing on consumer protection for the AI age. Think: safe transactional marketplaces, contextualized AI, and interoperable memory management.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Academic meets industry:&lt;/strong&gt; Practical solutions, experimental research, and policy influence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stanford Consumer AI Lab:&lt;/strong&gt; Where new ideas get dogfooded—and sometimes break stuff in spectacular fashion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  AI Security—The Agentic Future and Why It’s So Complex
&lt;/h2&gt;

&lt;p&gt;Back in the day, security meant writing boring permission lists and hoping users wouldn’t share passwords. Now, with autonomous agents, you need identity infrastructure where an AI can “roam the web,” interact, and actually DO things for you—not just scrape content.&lt;/p&gt;

&lt;p&gt;Key problems to solve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Delegated Authority:&lt;/strong&gt; How do you ensure an AI agent only acts with your explicit permission?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety Guarantees:&lt;/strong&gt; What does “safe” mean when an agent can kill processes and buy tickets on your behalf?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fine-Grained Authentication:&lt;/strong&gt; We’re moving beyond “all or nothing”—think scopes, context, and real-time oversight.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dr. South’s Stanford research group throws crazy ideas at the wall (“what if agents could actually perform actions for you online?”) and asks the hard questions about identity, permission, and safe delegation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stanford Lab &amp;amp; Consumer Protection in the AI Age
&lt;/h2&gt;

&lt;p&gt;It’s not just about writing safe code. What does consumer safety look like when you might soon be buying your next pair of pants through ChatGPT or Gemini? Stanford’s research lab runs experiments, advises students, and crafts real policy (like sections of the &lt;a href="https://www.un.org/en/ai-advisory-body/" rel="noopener noreferrer"&gt;UN International AI Safety Report&lt;/a&gt;) on privacy and security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does an academic research lab work?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with wild ideas—take them seriously.&lt;/li&gt;
&lt;li&gt;Ask students the off-the-wall questions (“what if agents roam the web?”).&lt;/li&gt;
&lt;li&gt;Conduct experiments to figure out what problems we need to solve.&lt;/li&gt;
&lt;li&gt;Feed findings into industry, policy, and standards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; As AI marketplaces, automation, and contextual memory get more complex, consumer safety requires new thinking—not just repackaging old IAM best practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Standards Get Built: The OpenID Foundation and Fast-Moving MCP
&lt;/h2&gt;

&lt;p&gt;Ever wondered how standards like OAuth, OpenID Connect, or MCP actually get written? According to Tobin, it’s equal parts collaboration, industry panic, and “LEGOs, not blueprints.” When the OpenID Foundation got curious about AI agents, Tobin helped launch a community group to pull together feedback from vendors, AI experts, and security pros.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic world:&lt;/strong&gt; MCP didn’t exist before October of last year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fastest white paper ever:&lt;/strong&gt; Industry is moving in real time, sometimes with “strongly held opinions in multiple directions.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP (Model Context Protocol):&lt;/strong&gt; Enables standardized tool calling and state management for AI agents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  OAuth 2.1, Dynamic Client Registration, and What’s Next for MCP
&lt;/h2&gt;

&lt;p&gt;Most security pros get nervous when words like "dynamic" and "client registration" pop up together. In the world of AI agents, it means your authorization server might need to let any agent connect—often pseudonymously. That sounds fun until you realize an agent could spawn a million applications in a single afternoon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recent changes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client ID metadata&lt;/strong&gt;—allows trusted agents (like Claude, ChatGPT) to declare themselves via DNS roots, so you don’t have to trust a random string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Client Registration (DCR)&lt;/strong&gt;—good for flexibility, but a big headache for security (“the wild west”).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Here's how it looks:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You get back a &lt;code&gt;client_id&lt;/code&gt; and &lt;code&gt;client_secret&lt;/code&gt;—but what’s to stop an agent from creating millions of these?&lt;/p&gt;

&lt;p&gt;For background on DCR, read &lt;a href="https://openid.net/specs/openid-connect-registration-1_0.html" rel="noopener noreferrer"&gt;OAuth’s Dynamic Client Registration documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Security Challenges of Dynamic Tools and Agents
&lt;/h2&gt;

&lt;p&gt;Imagine running VS Code and seeing a fresh OAuth client get created EVERY time you close and reopen your app. Or agents spawning millions of applications—each with their own keys and secrets. This is already happening in some test agents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Some agents create new applications each time&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Others reuse access tokens and clients&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lack of standardization makes security unpredictable&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why standardization matters:&lt;/strong&gt; As Tobin says,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The wild west of technology is... very fun right up until the scale and the importance gets a bit too large.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With AI, everything is happening at scale and speed we’ve never seen before. Even major players can’t keep up—hence the push for robust standards to ensure interoperability and safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  Natural Language Access Control—NLAC, SORA, and the Evolution Beyond RBAC
&lt;/h2&gt;

&lt;p&gt;Traditional access control models like RBAC (Role-Based Access Control), ABAC (Attribute-Based), and FGA (Fine-Grained Authorization) are starting to show their age—especially when AI agents interact via natural language. Enter NLAC—Natural Language Access Control—and new problems nobody saw coming.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: SORA App (AI Video Generation)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SORA lets you cameo friends in videos, turning on access so anyone can use your likeness. But the twist? You define what your AI deepfake can do using NATURAL LANGUAGE—just type it into a box.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“This is a crazy vision of the future of access controls on your own identity.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Problems with NLAC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s not standardized.&lt;/li&gt;
&lt;li&gt;Scopes may need to be described in natural language.&lt;/li&gt;
&lt;li&gt;Enforcing control over NL is much harder than simple permission strings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Agent-to-Agent Communication (A2A) — Natural Language, Power, and Worry
&lt;/h2&gt;

&lt;p&gt;Say you want Salesforce AgentForce to talk to ServiceNow Agent—should they use a rigid API, or a more flexible natural language interface? Most agent-to-agent comms will happen over MCP, supporting arbitrary text-based requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unprecedented flexibility&lt;/li&gt;
&lt;li&gt;More powerful than strictly structured APIs&lt;/li&gt;
&lt;li&gt;Easier automation and integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawback:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security is “terrifying”—hard to enforce precise control&lt;/li&gt;
&lt;li&gt;Restricting agents with scopes and permissions over NL remains challenging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next-gen approaches may require sending and enforcing natural language scopes throughout the web. It gives users power, but opens new risks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fine-grained Permissions: NLAC, SSO, SKIM, and Context Management
&lt;/h2&gt;

&lt;p&gt;We’re not likely to reinvent identity standards from scratch (“No, I don’t think we’re going to scan our eyeballs for World ID anytime soon”). Instead, Tobin argues we’ll adapt existing IAM protocols:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OAuth 2.1, SSO, SKIM:&lt;/strong&gt; Grabbing primitives from existing systems for provisioning and deprovisioning agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agentic Identity&lt;/strong&gt;: “Halfway between a service account and a user.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Problem: The complexity means OAuth standards (and MCP) will remain confusing and hard to use, but also robust.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real World: Setting Up an MCP Server the Right Way
&lt;/h2&gt;

&lt;p&gt;Anyone can wrap an API behind an MCP server and throw an API key behind it. But that’s just scratching the surface—if you want safety, flexibility, and proper permissions, you need to go deeper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical setup (v0):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Wrap APIs behind MCP.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add API key or OAuth for access.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect to Claude, ChatGPT, Gemini, etc.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Roll with it.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;But what’s wrong with this picture?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every user might supply an API key in unpredictable ways.&lt;/li&gt;
&lt;li&gt;Oauthing gives some identity, but how much access should you grant?&lt;/li&gt;
&lt;li&gt;Who controls which tools an agent can use, and when?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how Tobin suggests you level up your MCP server:&lt;/p&gt;

&lt;h3&gt;
  
  
  RBAC vs. Agent Trust
&lt;/h3&gt;

&lt;p&gt;Don’t just map roles to permission sets. When an AI agent acts on behalf of an admin, it could have excessive privilege—like the Netlify CEO who accidentally took down the company’s core website!&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Structured Tool Interfaces
&lt;/h3&gt;

&lt;p&gt;Instead of exposing every API as its own tool, create &lt;strong&gt;general-purpose tools&lt;/strong&gt; tailored to natural-language intents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing Secure, Scalable API Access for AI Agents
&lt;/h2&gt;

&lt;p&gt;Agents operate differently from humans. They can trigger API calls faster, in higher volume, and with less oversight. Standard dev-access patterns may be insufficient or dangerous.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One API key per agent?&lt;/strong&gt; Maybe for small use cases, but feels risky.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAuth tokens with scopes?&lt;/strong&gt; Good, but how detailed and granular should scopes be?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic tool access:&lt;/strong&gt; Assigning access per user or per role.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“Your server text—the tool description—can completely change based on who connected to the server.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impersonation, Delegated Authority, and the On-Behalf-Of Problem
&lt;/h2&gt;

&lt;p&gt;A common scenario: An executive assistant acts “on behalf of” the CEO, drafting or signing docs, but with more restrictions than the CEO herself. OAuth supports &lt;em&gt;on-behalf-of&lt;/em&gt; flows and delegated authority, but actual adoption (especially in consumer use cases) is still spotty.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Delegated Authority:&lt;/strong&gt; Needed, but not widely supported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumer vs. Enterprise:&lt;/strong&gt; Consumer platforms (Gemini, Claude, ChatGPT) own their agent ID; enterprises need robust audit, observability, and assurance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bottom-up adoption:&lt;/strong&gt; As agents grow, repeated patterns will emerge, and organizations will need to balance flexibility, visibility, and compliance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Workflows, Orchestrations, and Real-World Security
&lt;/h2&gt;

&lt;p&gt;Enter the orchestrators: Zapier, N8N, Google’s Agent SDK, OpenAI’s Agent SDK. Workflows let agents run asynchronously, acting on triggers and automating tasks across systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous agents:&lt;/strong&gt; Have distinct identity and access challenges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service accounts:&lt;/strong&gt; In essence, but with dynamic, context-driven permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-in-the-loop still needed:&lt;/strong&gt; Draft, review, and approve actions before sending.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This falls short of the holy grail—full workflow without constant approval—but strikes a balance between automation and oversight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fine-grained Access Control: FGA, NLAC, and Their Roles
&lt;/h2&gt;

&lt;p&gt;Fine-Grained Access (FGA) lets you enforce dynamic, per-resource permissions—great for complex systems like Google Drive, less so for fast-moving, flexible AI tools. NLAC promises something even more adaptable, using natural language conditions and rules, but it’s hard to standardize.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FGA:&lt;/strong&gt; Powerful, but complex and heavy-weight for many agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NLAC:&lt;/strong&gt; Flexible, emerging, but not standardized.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Demo MCP Server Implementing FGA
&lt;/h3&gt;

&lt;p&gt;Tobin built an MCP server where FGA is implemented INSIDE the server—tool descriptions and permissions are generated based on context, role, and conditions.&lt;/p&gt;

&lt;p&gt;This approach is tricky, and NLAC might eventually overtake FGA in simplicity and flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next for MCP: Statelessness, Metadata, and Why the Future Is Fast
&lt;/h2&gt;

&lt;p&gt;With the November 25th release of Model Context Protocol on the horizon, the most exciting development is &lt;em&gt;statelessness&lt;/em&gt; in protocol design, making implementation and security easier for everyone.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I’m very excited for a two-week rollout from a pure engineering perspective.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Other improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Transport layer fixes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client ID metadata&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better dev experience&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Responsibility in specs and standards&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As AI agents go mainstream, and as protocols like MCP evolve at record speed, the standardization and incremental improvements will go a long way toward making this wild ride safe for everyone.&lt;/p&gt;

&lt;p&gt;Curious to see all this in action, and hear more war stories from pioneers like Dr. Tobin South? Be sure to watch the &lt;a href="https://youtu.be/5SPm2CP6E5M" rel="noopener noreferrer"&gt;full video on YouTube&lt;/a&gt;, subscribe to our channel, and join the conversation below.&lt;/p&gt;

&lt;p&gt;What’s YOUR biggest challenge with access management for AI agents or MCP servers? Drop a comment, share your wins and “oops” moments, or let us know what you want to learn about next!&lt;/p&gt;

&lt;p&gt;And don’t forget to follow us for more deep dives into the cutting edge of web dev, security, and AI!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;External Must-Reads:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://workos.com" rel="noopener noreferrer"&gt;WorkOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openid.net/" rel="noopener noreferrer"&gt;OpenID Foundation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07" rel="noopener noreferrer"&gt;OAuth 2.1 RFC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/modelcontextprotocol" rel="noopener noreferrer"&gt;Model Context Protocol Spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.consumerreports.org/" rel="noopener noreferrer"&gt;Consumer Reports&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay curious, stay secure, and keep coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>podcast</category>
    </item>
    <item>
      <title>Firebase Firestore vs. Data Connect: Unlocking Your Data's Full Potential</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Sun, 19 Oct 2025 23:38:12 +0000</pubDate>
      <link>https://dev.to/codingcatdev/firebase-firestore-vs-data-connect-unlocking-your-datas-full-potential-1kf</link>
      <guid>https://dev.to/codingcatdev/firebase-firestore-vs-data-connect-unlocking-your-datas-full-potential-1kf</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/post/firebase-firestore-vs-data-connect-unlocking-your-data-s-full-potential" rel="noopener noreferrer"&gt;https://codingcat.dev/post/firebase-firestore-vs-data-connect-unlocking-your-data-s-full-potential&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey everyone, Alex here from CodingCat.dev! If you're like me, you absolutely love &lt;a href="https://firebase.google.com/docs/firestore" rel="noopener noreferrer"&gt;Firebase Firestore&lt;/a&gt;. It's incredibly powerful for building responsive, real-time applications with its seamless client-side SDKs. But have you ever hit a wall when you needed to run complex analytics, or do a full text search? You start thinking about setting up your own data pipelines, writing complex Cloud Functions to export data, and suddenly, the simplicity you loved about Firebase feels a little... complicated.&lt;/p&gt;

&lt;p&gt;What if there was a better way?&lt;/p&gt;

&lt;p&gt;That's where the new &lt;a href="https://firebase.blog/posts/2025/04/dataconnect-general-availability/" rel="noopener noreferrer"&gt;&lt;strong&gt;Firebase Data Connect&lt;/strong&gt;&lt;/a&gt; comes in, and it's a total game-changer. It bridges the gap between your real-time application data and the powerful world of GraphQL-based schemas.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Firebase Firestore? The Real-Time Powerhouse
&lt;/h3&gt;

&lt;p&gt;First, let's do a quick recap. Firebase Firestore is a flexible, scalable NoSQL cloud database for mobile, web, and server development.&lt;/p&gt;

&lt;p&gt;Its primary strengths are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Updates:&lt;/strong&gt; Data syncs across all connected clients automatically. This is the magic behind building live chat apps, collaborative documents, or real-time dashboards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Powerful Querying:&lt;/strong&gt; It has a rich SDK that allows for expressive queries directly from the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline Support:&lt;/strong&gt; It caches your app data so your app works smoothly, whether the user is online or offline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a classic example of adding a new user to a &lt;code&gt;users&lt;/code&gt; collection in a &lt;a href="https://firebase.google.com/codelabs/firebase-nextjs" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Purpose: Add a new user document to our Firestore collection.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDoc&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase/firestore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./firebase-config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Your initialized Firestore instance&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;addUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;setDoc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;createdAt&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User added successfully!&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error adding document: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This code is straightforward and perfect for handling application state. But if you wanted to find out how many users signed up last month, you'd have to fetch all the documents and process them, which isn't very efficient. This is the exact problem Data Connect is designed to solve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducing Firebase Data Connect: Your Data, Supercharged with SQL
&lt;/h3&gt;

&lt;p&gt;So, what exactly is &lt;a href="https://firebase.google.com/docs/data-connect" rel="noopener noreferrer"&gt;Firebase Data Connect&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Firebase Data Connect (FDC) is Firebase's first dedicated relational database solution for developers. It is a relational database service for mobile and web applications that allows you to build and scale secure apps using a fully-managed PostgreSQL database powered by Cloud SQL.   &lt;/p&gt;

&lt;p&gt;Data Connect is designed to bring the ease of use and rapid development of Firebase's ecosystem, but matched with a relational database offering that includes schema and powerful querying capabilities. It accelerates your app development by abstracting away the infrastructure management required to run your application. &lt;/p&gt;

&lt;p&gt;Below is a breakdown of how it works and what it delivers: &lt;/p&gt;

&lt;p&gt;The Magic: GraphQL, SQL, and Automation Data Connect operates by bridging the gap between your client application and the relational database using GraphQL.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Schema Definition: You define your application's data model using a schema. This schema explicitly maps to an underlying PostgreSQL database schema. You can even use Gemini AI assistance to generate your schema, queries, and mutations from just an app idea or a prompt. Data Connect will then automatically provision a Cloud SQL Postgres database and populate it with that schema.&lt;/li&gt;
&lt;li&gt;Query Generation: You declare the exact queries and mutations your application needs. When you craft these queries on your schema, Data Connect translates the GraphQL into SQL to read and write data to the Cloud SQL instance.&lt;/li&gt;
&lt;li&gt;Secure Endpoints: Data Connect is built on the principle: "You write the query, we do the rest". When you define a query, you instantly get a secure API endpoint with built-in authentication and authorization policy.&lt;/li&gt;
&lt;li&gt;Type-Safe SDKs: Data Connect simplifies client-side development by automatically generating typesafe SDKs for Android, iOS, Flutter, and web, based on your predefined queries. These generated SDKs allow you to call the database with a single line from your client. Data Connect is essentially a "self-driving app server" made-to-order for your specific application. Solving Complex Data Problems Data Connect shines when you move beyond simple application state management and need serious data horsepower:&lt;/li&gt;
&lt;li&gt;Advanced Aggregation and Analytics For the complex queries, like "how many users signed up last month," Data Connect enables powerful aggregations using View types. This special type allows you to write arbitrary SQL SELECT statements and bind them relationally to your GraphQL data model. This means you can pull in review statistics or other calculated metrics efficiently alongside your application data.&lt;/li&gt;
&lt;li&gt;Full-Text and Semantic Search FDC directly solves the need for advanced search capabilities through its integration with Vertex AI Text embeddings. • Vector Embeddings: A vector embedding represents the meaning of an object (like a movie title or description) as understood by AI in a multi-dimensional space. • Semantic Search: Data Connect makes it easy to generate these vector embeddings and store them in Cloud SQL. When a user enters a search term, Data Connect generates an embedding from Vertex AI and executes a similarity search for related data within Cloud SQL. This enables semantic search that finds results based on the meaning of the search, not just exact text matches. For instance, searching for "mythical creatures" can return highly relevant movies even if those words aren't in the title.&lt;/li&gt;
&lt;li&gt;Powering AI Agents Beyond traditional application development, Data Connect is also used to power AI agents. It generates tool definitions for LLMs (Large Language Models). This allows an agent, built using frameworks like Genkit, to access data in your database by calling Data Connect queries and mutations as tools. This process, known as Retrieval-Augmented Generation (RAG), grounds the AI's response in your specific database context.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Make sure to check out this video about &lt;a href="https://youtu.be/N25khadfUag" rel="noopener noreferrer"&gt;Firebase Data Connect&lt;/a&gt; that I did with Google Engineer Tyler Crowe for even more details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thinking in GraphQL: A Quick Primer
&lt;/h3&gt;

&lt;p&gt;At the heart of Firebase Data Connect is &lt;strong&gt;GraphQL&lt;/strong&gt;, a query language for your API. Unlike traditional REST APIs, where you often have to make multiple requests to fetch related data, GraphQL allows you to request exactly the data you need in a single query.&lt;/p&gt;

&lt;p&gt;Think of it like ordering a pizza. With a REST API, you might have to first order the crust, then the sauce, then each topping individually. With GraphQL, you can place a single order with all your desired toppings, and get exactly what you asked for, all at once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing Your First Queries
&lt;/h3&gt;

&lt;p&gt;Let's dive into some practical examples from the codelab. The codelab builds a movie review application, so our queries will be centered around movies, actors, and reviews.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fetching a Single Movie
&lt;/h4&gt;

&lt;p&gt;To fetch a single movie by its ID, you would write a query like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetMovieById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;imageUrl&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;releaseYear&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;genre&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;Here's a breakdown of what's happening:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;query GetMovieById($id: UUID!)&lt;/code&gt;&lt;/strong&gt;: This defines the query and its name, &lt;code&gt;GetMovieById&lt;/code&gt;. It also specifies a variable &lt;code&gt;$id&lt;/code&gt; of type &lt;code&gt;UUID!&lt;/code&gt; that will be passed to the query. The &lt;code&gt;!&lt;/code&gt; means that this variable is required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;movie(id: $id)&lt;/code&gt;&lt;/strong&gt;: This is the root field of our query. We're asking for a &lt;code&gt;movie&lt;/code&gt; and passing the &lt;code&gt;$id&lt;/code&gt; variable to specify which movie we want.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;{ id title ... }&lt;/code&gt;&lt;/strong&gt;: This is the selection set. We're telling GraphQL exactly which fields we want to retrieve for the movie.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Fetching Related Data
&lt;/h4&gt;

&lt;p&gt;Now, let's say we want to fetch a movie along with its main actors and reviews. With GraphQL, this is as simple as extending our selection set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetMovieById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;mainActors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;actors_via_MovieActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"main"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;imageUrl&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reviews_on_movie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;reviewText&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;In this query, we've added &lt;code&gt;mainActors&lt;/code&gt; and &lt;code&gt;reviews&lt;/code&gt; to our selection set. We're also using a &lt;code&gt;where&lt;/code&gt; clause to filter the &lt;code&gt;actors_via_MovieActor&lt;/code&gt; to only include actors with the role of "main".&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutations: Changing Your Data
&lt;/h3&gt;

&lt;p&gt;GraphQL isn't just for fetching data; it's also for modifying it. In GraphQL, these operations are called &lt;strong&gt;mutations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's say we want to add a new user to our database. We can define a mutation like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user_insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;This mutation, named &lt;code&gt;CreateUser&lt;/code&gt;, takes the user's &lt;code&gt;uid&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;name&lt;/code&gt; as arguments and uses the &lt;code&gt;user_insert&lt;/code&gt; mutation to add a new user to the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maybe you should try Data Connect
&lt;/h3&gt;

&lt;p&gt;Firebase Data Connect, with its GraphQL-powered interface, offers a flexible and efficient way to work with your relational data. By allowing you to specify exactly the data you need, it can significantly improve the performance of your applications and simplify your data-fetching logic. The examples above are just the tip of the iceberg, and I encourage you to explore the official &lt;a href="https://github.com/FirebaseExtended/codelab-dataconnect-web/tree/main/dataconnect" rel="noopener noreferrer"&gt;codelab&lt;/a&gt; and documentation to discover all that Data Connect has to offer.&lt;/p&gt;

&lt;p&gt;To see an introduction to Firebase Data Connect, and how it uses SQL, see the following video: &lt;a href="https://www.youtube.com/watch?v=7OdVatEI85o" rel="noopener noreferrer"&gt;Introducing Data Connect&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Running the Cloud on Your Desktop with LocalStack</title>
      <dc:creator>Alex Patterson</dc:creator>
      <pubDate>Sun, 12 Oct 2025 23:15:42 +0000</pubDate>
      <link>https://dev.to/codingcatdev/running-the-cloud-on-your-desktop-with-localstack-3f76</link>
      <guid>https://dev.to/codingcatdev/running-the-cloud-on-your-desktop-with-localstack-3f76</guid>
      <description>&lt;p&gt;Original: &lt;a href="https://codingcat.dev/podcast/running-the-cloud-on-your-desktop-with-localstack" rel="noopener noreferrer"&gt;https://codingcat.dev/podcast/running-the-cloud-on-your-desktop-with-localstack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt;Welcome back, perfect peeps! Today we’re diving deep into how to bring the power of AWS to your local machine using &lt;a href="https://localstack.cloud/" rel="noopener noreferrer"&gt;LocalStack&lt;/a&gt;. If you build cloud-native apps, dabble in side hustles as a solopreneur, or want to experiment with AWS services without racking up a bill, this is the post for you. You’ll learn what LocalStack is, why it’s awesome, and how to use it—from setting up buckets to working with Lambdas, CDK, CI/CD, and beyond.&lt;/p&gt;

&lt;p&gt;Grab your favorite mug (mine’s a Netlify mug with way too much coffee in it), sit back, and let’s see how LocalStack can seriously change up your cloud development workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet the Hosts: Catching Up
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“I think it’s actually been about three years since you’ve been on the show, which is insane to me.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you’ve tuned in before, you’ll recognize your hosts from the &lt;a href="https://codingcat.dev/podcasts/devrel" rel="noopener noreferrer"&gt;DevRel&lt;/a&gt; (developer relations) world: Brian Reinaldi, previously at LaunchDarkly and now at LocalStack, and Alex, your guide here at &lt;a href="https://codingcat.dev/" rel="noopener noreferrer"&gt;CodingCat.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like so many of us, Brian juggles a full-time gig with a bunch of side projects (check out &lt;a href="https://cfe.dev" rel="noopener noreferrer"&gt;cfe.dev&lt;/a&gt; for his event lineup). Burnout happens, life gets busy, and conference schedules never slow down. But the passion for sharing cool tools survives! That’s why Brian’s here to give us the rundown on how LocalStack has changed his approach to both work and play.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is LocalStack?
&lt;/h2&gt;

&lt;p&gt;If you’ve ever dipped your toes in AWS, you probably know the pain: spinning up resources is slow, can get expensive, and—let’s be honest—just plain scary when you’re learning. Enter LocalStack.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-Level Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;LocalStack&lt;/strong&gt; is basically AWS on your laptop. You get a Docker image that emulates AWS services locally, so you can spin up buckets, run lambdas, use API Gateway, and much more—without ever touching your actual AWS account.&lt;/p&gt;

&lt;p&gt;You don’t need to sign up for an AWS free tier. You don’t have to worry about forgetting to tear down an EC2 instance (and getting surprising bills). Instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You experiment and build &lt;strong&gt;locally&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Everything is &lt;strong&gt;ephemeral&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You control costs (no “I left a GPU running all weekend” horror stories)&lt;/li&gt;
&lt;li&gt;Debugging, iteration, and CI/CD are all &lt;strong&gt;much, much faster&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you can reset and restart as often as you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Free vs Paid
&lt;/h3&gt;

&lt;p&gt;LocalStack has two flavors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open Source&lt;/strong&gt; (Free)

&lt;ul&gt;
&lt;li&gt;~30 AWS services (S3, Lambda, API Gateway, CloudFront, etc.)&lt;/li&gt;
&lt;li&gt;Use as much as you want, forever&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Pro / Paid&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;~120 AWS services emulated (and counting)&lt;/li&gt;
&lt;li&gt;Premium features: more services, tools for debugging, step-through, chaos engineering, more&lt;/li&gt;
&lt;li&gt;This is how the LocalStack team eats (support them!)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Which Services Are Covered?
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“We have like really close parity with AWS on certain services (like S3 &amp;amp; Lambda)... Some APIs are partial. But for core stuff, we’re very close.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AWS itself has ~300 services, but most modern apps rely on a handful: S3, Lambda, API Gateway, DynamoDB, CloudFront. For these, LocalStack hits near parity with AWS. For edge-case services or those you almost never use, some features may lag behind.&lt;/p&gt;

&lt;p&gt;Check out their &lt;a href="https://docs.localstack.cloud/references/aws-services/" rel="noopener noreferrer"&gt;full list of supported services&lt;/a&gt; to see if your stack is covered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main Features
&lt;/h3&gt;

&lt;p&gt;Some of the headline goodies you’ll find in LocalStack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Run dozens of AWS services locally&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step Debugging:&lt;/strong&gt; Attach a debugger to your (Node.js) lambdas, set breakpoints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hot Reload:&lt;/strong&gt; Save your code, instantly test the change, no manual deploys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaos Engineering:&lt;/strong&gt; Simulate API slowdowns, outages, or dropped packets to test how your app handles “the real world”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web-based UI&lt;/strong&gt;: Inspect resources, invoke lambdas, and debug from your browser&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thin Wrappers for CLI Tools:&lt;/strong&gt; Keep your workflow—just redirect commands to “local”&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“The real savings isn’t just the money. It’s the time you save as a developer. Tests that took 45 minutes now take just a few minutes.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setting Up LocalStack – Step By Step
&lt;/h2&gt;

&lt;p&gt;Okay, let’s get hands-on. Here’s how to set up LocalStack on YOUR laptop, with tips straight from Brian and Alex.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Docker Flow
&lt;/h3&gt;

&lt;p&gt;LocalStack runs as a &lt;strong&gt;Docker container&lt;/strong&gt;. So:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/get-started/" rel="noopener noreferrer"&gt;&lt;strong&gt;Install Docker&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull LocalStack:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull localstack/localstack

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run LocalStack:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 &lt;span class="nt"&gt;-p&lt;/span&gt; 4510-4559:4510-4559 localstack/localstack

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;By default, LocalStack runs with GUI/API access on port &lt;code&gt;4566&lt;/code&gt;. (Side note: multiple ports are used internally.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install the CLI wrapper&lt;/strong&gt; (optional, but way easier):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;localstack-client

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

&lt;/div&gt;



&lt;p&gt;Or grab their &lt;a href="https://docs.localstack.cloud/get-started/cli/" rel="noopener noreferrer"&gt;LocalStack CLI&lt;/a&gt; for more features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web App UI: Not Just for the Cloud
&lt;/h3&gt;

&lt;p&gt;Here’s something wild: &lt;strong&gt;LocalStack’s web UI runs on your laptop&lt;/strong&gt;, but acts just like a cloud console.&lt;/p&gt;

&lt;p&gt;What’s actually happening:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The web app connects to your local Docker instance&lt;/li&gt;
&lt;li&gt;You browse buckets, lambdas, APIs…the whole works&lt;/li&gt;
&lt;li&gt;Everything is still 100% local to YOUR machine&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“People actually get confused. They open the web app and think, ‘Wait, is this running in the cloud?’ Nope! It’s all on your box. But with all the power of a cloud console.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Learning AWS for Real: Project Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CDK, CloudFormation &amp;amp; Infrastructure as Code
&lt;/h3&gt;

&lt;p&gt;To get serious with AWS, you’ll want &lt;strong&gt;Infrastructure as Code&lt;/strong&gt;. Brian’s example uses &lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/home.html" rel="noopener noreferrer"&gt;CDK (Cloud Development Kit)&lt;/a&gt;—a tool that lets you build AWS resources in TypeScript, Python, etc., then transpile down to CloudFormation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CDK Stack:&lt;/strong&gt; Write resources like &lt;code&gt;new s3.Bucket()&lt;/code&gt; or &lt;code&gt;new lambda.Function()&lt;/code&gt; in your preferred language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bootstrapping:&lt;/strong&gt; CDK zips everything up, creates CloudFormation, and shoves it into S3 for deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy:&lt;/strong&gt; Actually builds resources locally—in our case, via LocalStack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workflow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start LocalStack (make sure Docker is running)&lt;/span&gt;
localstack start
&lt;span class="c"&gt;# Run CDK locally (not on AWS)&lt;/span&gt;
cdk-local bootstrapcdk-local deploy

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you’re used to writing TF with &lt;a href="https://terraform.io" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt;, this is a super similar flow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Makefiles for Convenience
&lt;/h4&gt;

&lt;p&gt;Brian uses a &lt;code&gt;Makefile&lt;/code&gt; to automate all his steps, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;deploy-s3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;cdk-local bootstrapcdk-local deploy&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;So he can just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make deploy-s3

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

&lt;/div&gt;



&lt;p&gt;Easy button!&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: S3 Static Site Hosting
&lt;/h3&gt;

&lt;p&gt;Let’s walk through building a basic &lt;strong&gt;static site&lt;/strong&gt;—think Netlify in the early days, just HTML/CSS/JS.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. CDK Stack Definition
&lt;/h4&gt;

&lt;p&gt;Here’s (roughly) what your TypeScript CDK stack might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-s3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StackProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyStaticSiteStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&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="nx"&gt;props&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;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MySiteBucket&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="na"&gt;websiteIndexDocument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="na"&gt;websiteErrorDocument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="na"&gt;publicReadAccess&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;cors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; 
                &lt;span class="na"&gt;allowedMethods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HttpMethods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                &lt;span class="na"&gt;allowedOrigins&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;*&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="na"&gt;enforceSSL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="p"&gt;});&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What’s going on?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defines an S3 bucket for static website hosting&lt;/li&gt;
&lt;li&gt;Enables public read, sets index/error documents, CORS, and SSL&lt;/li&gt;
&lt;li&gt;(Optionally) Uses S3 deployment to push static files into the bucket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Assets:&lt;/strong&gt; Your &lt;code&gt;/site-assets&lt;/code&gt; folder holds &lt;code&gt;index.html&lt;/code&gt;, &lt;code&gt;styles.css&lt;/code&gt;, JS, etc.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Deploy Locally
&lt;/h4&gt;

&lt;p&gt;With LocalStack running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make deploy-s3
&lt;span class="c"&gt;# or directly:&lt;/span&gt;
cdk-local bootstrapcdk-local deploy

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Inspect in the Web UI
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Open the LocalStack web app&lt;/li&gt;
&lt;li&gt;Browse to the S3 bucket&lt;/li&gt;
&lt;li&gt;See your static assets: &lt;code&gt;index.html&lt;/code&gt;, JS, CSS, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Access the Hosted Site
&lt;/h4&gt;

&lt;p&gt;LocalStack gives you a special URL pointing to &lt;strong&gt;your local instance&lt;/strong&gt;, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://bucketname.localstack.cloud:4566/index.html

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

&lt;/div&gt;



&lt;p&gt;Open in your browser. You’ll see your static site, &lt;em&gt;served&lt;/em&gt; by a local clone of AWS S3.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Blockquote&lt;/strong&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“I'm doing this all locally. This is running, if you see that URL, it's actually pointing at your local instance... Not in the cloud, running on my machine.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  5. Bypass Annoyances
&lt;/h4&gt;

&lt;p&gt;Working on the real cloud often hits you with CORS errors or IAM permission headaches. LocalStack lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Disable CORS&lt;/strong&gt; for easier development&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bypass IAM&lt;/strong&gt; (security) during dev, then enable to test before pushing to prod&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more on &lt;a href="https://docs.localstack.cloud/references/aws-services/#s3" rel="noopener noreferrer"&gt;local AWS S3 restrictions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  From S3 to Global: Adding CloudFront
&lt;/h3&gt;

&lt;p&gt;Let’s make things more “real world.” You want to deploy your site &lt;strong&gt;globally&lt;/strong&gt; (via CDN) instead of from a single S3 bucket.&lt;/p&gt;

&lt;h4&gt;
  
  
  What’s New?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;CloudFront&lt;/strong&gt; distribution in your CDK stack&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CloudFront&lt;/strong&gt; sits in front of your S3 bucket&lt;/li&gt;
&lt;li&gt;Disables public access on S3 (only CloudFront has access)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Access the CDN-Backed Site
&lt;/h4&gt;

&lt;p&gt;The app is almost identical visually, but now served through a global CDN—&lt;em&gt;and still completely local.&lt;/em&gt; Sound slow? Actually, on LocalStack, these setups build in seconds, not minutes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“A CloudFront distribution can be super slow to deploy to AWS... This is going to deploy in a matter of seconds with Lambda, CloudFront, and S3.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Serverless Power: Adding Lambdas
&lt;/h3&gt;

&lt;p&gt;Static sites are fun, but sometimes you want server-side logic. Enter AWS Lambda.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Basic Lambda Example (Node.js)
&lt;/h4&gt;

&lt;p&gt;Lambda handler file (e.g., &lt;code&gt;src/handler.js&lt;/code&gt;):&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="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&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;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;body&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="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;Hello from Lambda!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;&lt;span class="na"&gt;headers&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="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}};&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Add Lambda to Your CDK Stack
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-lambda&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;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyFn&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="na"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODEJS_18_X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;handler.handler&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/&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;h4&gt;
  
  
  3. Expose via Lambda Function URL
&lt;/h4&gt;

&lt;p&gt;You can create a public URL to hit your Lambda directly (for demos, not production!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fnUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FunctionUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FnUrl&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="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;authType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FunctionUrlAuthType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NONE&lt;/span&gt;&lt;span class="p"&gt;,});&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Deploy, Test, and Play
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Deploy with &lt;code&gt;make deploy-lambda&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;LocalStack instantly exposes your &lt;code&gt;functionUrl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Hit it in your browser or with &lt;code&gt;curl&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://function-id.localstack.cloud:4566/# &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"message"&lt;/span&gt;: &lt;span class="s2"&gt;"Hello from Lambda!"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Web UI FTW
&lt;/h4&gt;

&lt;p&gt;Invoke the lambda, add debug payloads, and get instant feedback via the web app. No more click-wait-refresh nightmares!&lt;/p&gt;

&lt;h3&gt;
  
  
  API Gateway: Real-World Full Stack
&lt;/h3&gt;

&lt;p&gt;Now, let’s build a &lt;strong&gt;real API&lt;/strong&gt; like you’d use for your single-page app’s backend.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Integrate Lambda With API Gateway
&lt;/h4&gt;

&lt;p&gt;Instead of exposing your lambda directly, route it through API Gateway.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;apigateway&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-apigateway&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;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;apigateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RestApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyAPI&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;getIntegration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;apigateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LambdaIntegration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resourceForPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getIntegration&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, when you hit &lt;code&gt;/hello&lt;/code&gt; on the API endpoint, it triggers your lambda!&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Deploy &amp;amp; Call
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make deploy-apigateway

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

&lt;/div&gt;



&lt;p&gt;Get the API endpoint (from CDK outputs or the web UI):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api-id.localstack.cloud:4566/hello

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

&lt;/div&gt;



&lt;p&gt;Visit in the browser or use your front-end code to call this endpoint.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Put It All Together
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;S3 hosts the static site&lt;/li&gt;
&lt;li&gt;CloudFront sits in front as a CDN&lt;/li&gt;
&lt;li&gt;API Gateway exposes endpoints&lt;/li&gt;
&lt;li&gt;Lambda runs your server code&lt;/li&gt;
&lt;li&gt;All running locally&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“This is now calling somewhat getting closer to a real app... not just a function URL endpoint, but an API, hit by the front-end.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Bonus: Other AWS Services
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Want more?&lt;/strong&gt; LocalStack (even in the free version) supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DynamoDB:&lt;/strong&gt; Run a NoSQL backend locally for your app or play with familiar Dynamo queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSM (Systems Manager) / Secrets Manager:&lt;/strong&gt; Store environment variables, secrets, and config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM:&lt;/strong&gt; Simulate auth rules (can be turned off/on to make life easier in dev)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use thin wrappers for AWS CLI, CloudFormation, Terraform, CDK, and more.&lt;/p&gt;

&lt;p&gt;Example CLI wrapper usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 s3 &lt;span class="nb"&gt;ls&lt;/span&gt;&lt;span class="c"&gt;# Or use localstack's own CLI for extra features&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“We even have a tool (Pro) called IAM Policy Stream that actually tells you what IAM policies you're missing for different services!”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Debugging, Hot Reload, and Chaos Engineering
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step Debugging
&lt;/h3&gt;

&lt;p&gt;With Pro, add breakpoints to your serverless functions, use your favorite IDE, and step through lambdas—something most AWS users only dream about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hot Reload
&lt;/h3&gt;

&lt;p&gt;Saving your lambda code triggers instant reload and redeploy. No more &lt;code&gt;zip &amp;amp;&amp;amp; upload &amp;amp;&amp;amp; test&lt;/code&gt; loops.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chaos Engineering
&lt;/h3&gt;

&lt;p&gt;Want to make sure your app doesn’t break if AWS throws a wrench in the works? LocalStack lets you simulate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow network calls (latency injection)&lt;/li&gt;
&lt;li&gt;Dropped packets (simulate outages)&lt;/li&gt;
&lt;li&gt;AWS API failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Great for modern observability/testing practices!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“You’d be surprised how often packets are lost or latency spikes in the real world. Now you can test your resilience before you ship!”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  LocalStack in Your Workflow: CI/CD &amp;amp; Team Dev
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Developer Workflow
&lt;/h3&gt;

&lt;p&gt;Picture this: Two developers are working on a feature, each running LocalStack on their laptops.&lt;/p&gt;

&lt;p&gt;Workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Each dev spins up LocalStack locally&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Modifies CDK or Terraform code&lt;/li&gt;
&lt;li&gt;Tests lambdas, endpoints, etc., with full hot reload and step debugging&lt;/li&gt;
&lt;li&gt;Commits to git&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  CI/CD Pipeline Integration
&lt;/h3&gt;

&lt;p&gt;Teams often spin up &lt;strong&gt;test environments&lt;/strong&gt; on AWS for every pull request (expensive and slow). With LocalStack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI/CD pipeline pulls your code&lt;/li&gt;
&lt;li&gt;Spins up LocalStack Docker container&lt;/li&gt;
&lt;li&gt;Deploys your full app to &lt;strong&gt;local stack&lt;/strong&gt; in the CI runner&lt;/li&gt;
&lt;li&gt;Runs integration and unit tests (all local, zero cloud costs)&lt;/li&gt;
&lt;li&gt;If everything passes, deploys to AWS&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Benefits
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;No more “who forgot to shutdown the test instance?” bills&lt;/li&gt;
&lt;li&gt;CI builds run faster (tests go from 45min to 2min in some cases)&lt;/li&gt;
&lt;li&gt;Easy rollbacks (just restart local stack)&lt;/li&gt;
&lt;li&gt;Fast local feedback = more experimentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Speed Gains
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“It’s all faster! Unless you’re paying Buco bucks for your AWS builds, nothing beats your own dev laptop for speed.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What’s Next for LocalStack? Beyond AWS
&lt;/h2&gt;

&lt;p&gt;LocalStack started as “AWS locally,” but their dream is &lt;strong&gt;multi-cloud on your laptop&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  GCP, Azure, and More
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake Emulator:&lt;/strong&gt; Already in pre-release (for data science workflow fans)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure:&lt;/strong&gt; On the roadmap, with early experimental bits already out there&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GCP:&lt;/strong&gt; No timeline yet, but definitely a future goal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Connections:&lt;/strong&gt; Hook up LocalStack to third-party providers (like Okta, Auth0, etc.) easily&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Big vision: Whatever you do on the cloud, you should be able to do locally in LocalStack—across AWS, Azure, and GCP.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Why Multi-Cloud?
&lt;/h3&gt;

&lt;p&gt;Companies rarely stick with one provider forever. Multi-cloud is on the rise, and being able to test &lt;strong&gt;any&lt;/strong&gt; cloud workflow locally is going to be a must.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts &amp;amp; Resources
&lt;/h2&gt;

&lt;p&gt;After using LocalStack, Brian’s main takeaway is &lt;strong&gt;speed&lt;/strong&gt; and freedom. It’s not just about saving money—it’s making cloud development fun to experiment with again.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“It let me experiment and iterate without all the pain and delay. Now I’m more likely to try new things, mess with new APIs, because it’s so fast and safe.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All the demos we saw today (including Lambda, S3, CloudFront, API Gateway, and even DynamoDB) are included in the free version, so you can start experimenting without spending a dime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources &amp;amp; More Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.localstack.cloud/" rel="noopener noreferrer"&gt;LocalStack Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/home.html" rel="noopener noreferrer"&gt;CDK Intro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/cloudformation/" rel="noopener noreferrer"&gt;AWS CloudFormation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.terraform.io/intro" rel="noopener noreferrer"&gt;Terraform 101&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://localstack.cloud/use-cases/serverless/" rel="noopener noreferrer"&gt;Working with Serverless on LocalStack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codingcat.dev/podcasts" rel="noopener noreferrer"&gt;CodingCat.dev Podcasts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For extra hands-on guides and new episodes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://codingcat.dev/posts/aws-full-stack-easy" rel="noopener noreferrer"&gt;How to Deploy Full-Stack Apps to AWS the Easy Way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codingcat.dev/posts/serverless-secrets-lambdas" rel="noopener noreferrer"&gt;Serverless Secrets: Deploy Lambdas in Seconds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codingcat.dev/posts/cicd-intro" rel="noopener noreferrer"&gt;Intro to CI/CD for Startups&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Join the Conversation
&lt;/h1&gt;

&lt;p&gt;Have questions? Want to share your horror stories (or victories) using LocalStack? Hit us up at &lt;a href="https://x.com/codingcatdev" rel="noopener noreferrer"&gt;@CodingCatDev&lt;/a&gt; or drop a comment below!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>podcast</category>
    </item>
  </channel>
</rss>
