<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Ali Builds]]></title><description><![CDATA[Building and optimizing: tech products, work systems, and team processes. Documenting what actually works.]]></description><link>https://www.ali-b.com</link><image><url>https://substackcdn.com/image/fetch/$s_!A_8a!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F25c3b919-556e-43d9-902a-f0e23cc50227_350x350.jpeg</url><title>Ali Builds</title><link>https://www.ali-b.com</link></image><generator>Substack</generator><lastBuildDate>Sat, 11 Apr 2026 19:28:08 GMT</lastBuildDate><atom:link href="https://www.ali-b.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Ali B]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[alibadereddin@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[alibadereddin@substack.com]]></itunes:email><itunes:name><![CDATA[Ali B]]></itunes:name></itunes:owner><itunes:author><![CDATA[Ali B]]></itunes:author><googleplay:owner><![CDATA[alibadereddin@substack.com]]></googleplay:owner><googleplay:email><![CDATA[alibadereddin@substack.com]]></googleplay:email><googleplay:author><![CDATA[Ali B]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[We Built Bridges to AI, But Not Between Our Tools]]></title><description><![CDATA[Moved from Medium. Original Post Date: June 28th 2025.]]></description><link>https://www.ali-b.com/p/we-built-bridges-to-ai-but-not-between</link><guid isPermaLink="false">https://www.ali-b.com/p/we-built-bridges-to-ai-but-not-between</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 15:01:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!SeU4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was deep in a conversation with Claude on my desktop, working through a complex problem. We&#8217;d explored the architecture, discussed trade-offs, and sketched out some code. Then I realized I needed to switch to Claude Code to actually implement it.</p><p>Starting over in a new chat felt like leaving a good conversation mid-sentence.</p><p>This friction point revealed something profound: We have the Model Context Protocol (MCP) connecting AI to tools. But we&#8217;ve only solved half the problem. What if we could build on MCP&#8217;s success to create something bigger&#8202;&#8212;&#8202;a Universal Context Protocol (UCP) that connects ALL our tools through shared context?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SeU4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SeU4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!SeU4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!SeU4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!SeU4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SeU4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SeU4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!SeU4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!SeU4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!SeU4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff96e24-215d-4049-b76a-dbbda24bcf19_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Bridges between tools</figcaption></figure></div><h3>MCP&#8217;s Success Shows the Way</h3><p>MCP proved something important: tools can communicate through standardized protocols. It elegantly solved AI-to-tool communication:</p><ul><li><p>Claude &#8594; (MCP) &#8594; Your Database</p></li><li><p>Claude &#8594; (MCP) &#8594; Your Files</p></li><li><p>Claude &#8594; (MCP) &#8594; Your APIs</p></li></ul><p>But our tools still can&#8217;t talk to each other:</p><ul><li><p>Figma &#10060; Cursor</p></li><li><p>Claude Desktop &#10060; Claude Code</p></li><li><p>Your IDE &#10060; Your Design Tools</p></li></ul><p>We&#8217;ve built bridges to AI, but not between our tools. It&#8217;s like having phones that can only call the operator, not each other.</p><h3>Introducing UCP: Universal Context Protocol</h3><p>What if we leveraged MCP&#8217;s architecture to create UCP&#8202;&#8212;&#8202;a protocol specifically designed for tool-to-tool context sharing?</p><pre><code>MCP (Model Context Protocol):
Tool &#8592;&#8594; AI Model</code></pre><pre><code>UCP (Universal Context Protocol):
Tool &#8592;&#8594; Shared Context &#8592;&#8594; Tool
         &#8593;
    AI (via MCP)</code></pre><p>UCP wouldn&#8217;t replace MCP&#8202;&#8212;&#8202;it would complement it. MCP handles AI connections. UCP handles everything else.</p><h3>How UCP Would Work</h3><p><strong>Note: This example is simplified to demonstrate the concept.</strong> Real implementation would require sophisticated protocols, but the principle is clear:</p><pre><code># Project context accessible via UCP
project: RealtimeCollaboration
ucp_id: "rtc-2024-03"

# Tools register with UCP
registered_tools:
  - name: "Claude Desktop"
    mcp_enabled: true
    publishes: ["decisions", "explorations"]
    subscribes: ["code_changes", "design_updates"]
    
  - name: "Figma"
    mcp_enabled: false
    publishes: ["design_tokens", "components"]
    subscribes: ["code_constraints", "decisions"]
    
  - name: "Cursor"
    mcp_enabled: true
    publishes: ["code_patterns", "implementations"]
    subscribes: ["design_tokens", "architecture"]
# Live context flow via UCP
context_streams:
  design_decisions:
    source: "Figma"
    data: {colors: "#FF6B6B", animations: "200ms ease"}
    subscribers: ["Cursor", "Claude Desktop", "Claude Code"]
    
  architecture_choices:
    source: "Claude Desktop"
    data: {pattern: "WebSocket", reason: "existing infrastructure"}
    subscribers: ["Cursor", "Figma", "Documentation"]
    
  implementation_status:
    source: "Cursor"
    data: {feature: "cursor_tracking", status: "complete"}
    subscribers: ["Claude Code", "Project Manager"]</code></pre><h3>UCP + MCP: The Complete Picture</h3><p>The beauty is how they work together:</p><ol><li><p><strong>MCP</strong> connects AI to individual tools (proven, working today)</p></li><li><p><strong>UCP</strong> connects tools to each other through shared context (the missing piece)</p></li><li><p><strong>AI</strong> becomes smarter because it can see the full context via both protocols</p></li></ol><p>Your workflow becomes:</p><ul><li><p>Open any tool &#8594; UCP provides full project context</p></li><li><p>Need AI help &#8594; MCP connects to AI with rich context</p></li><li><p>Switch tools &#8594; Context flows seamlessly via UCP</p></li><li><p>Collaborate &#8594; Everyone shares the same living context</p></li></ul><h3>What UCP Enables</h3><p><strong>True Continuity</strong>: Start in Claude Desktop, continue in Claude Code&#8202;&#8212;&#8202;same conversation, because UCP maintains the thread.</p><p><strong>Real-time Sync</strong>: Change a design token in Figma, your IDE instantly knows via UCP. No manual updates, no disconnected systems.</p><p><strong>Tool Intelligence</strong>: Every tool understands what every other tool is doing. Your IDE knows what you designed. Your design tool knows your code constraints.</p><p><strong>Project Memory</strong>: Your project&#8217;s context lives independently, accessible via UCP. It&#8217;s yours, not trapped in any tool.</p><h3>Why This Completes the AI OS</h3><p>An operating system needs:</p><ol><li><p><strong>Resource Management</strong>: UCP manages context as a shared resource</p></li><li><p><strong>Inter-Process Communication</strong>: UCP is literally IPC for the AI age</p></li><li><p><strong>Standard Protocols</strong>: MCP for AI, UCP for everything else</p></li><li><p><strong>Security Layer</strong>: UCP can handle permissions and access control</p></li></ol><p>We don&#8217;t need to replace traditional operating systems. We need to add the context layer they&#8217;re missing&#8202;&#8212;&#8202;and UCP can be that layer.</p><h3>Breaking Free from Tool Prisons</h3><p>Today&#8217;s &#8220;project&#8221; features fail because they&#8217;re silos:</p><ul><li><p>Claude Projects &#8594; Locked in Claude</p></li><li><p>Claude Code&#8217;s <code>.md</code> &#8594; Stuck in Claude Code</p></li><li><p>Cursor&#8217;s context &#8594; Trapped in Cursor</p></li></ul><p>With UCP:</p><ul><li><p>Project context lives independently</p></li><li><p>Tools connect through UCP to access it</p></li><li><p>Context flows freely between everything</p></li><li><p>You own your project&#8217;s memory</p></li><li><p>MCP still handles AI connections</p></li></ul><h3>The Path Forward</h3><p>This isn&#8217;t starting from scratch&#8202;&#8212;&#8202;it&#8217;s building on what works:</p><ol><li><p><strong>Leverage MCP&#8217;s design</strong> principles for UCP</p></li><li><p><strong>Define context schemas</strong> that any tool can use</p></li><li><p><strong>Build UCP adapters</strong> for popular tools</p></li><li><p><strong>Create bridges</strong> between UCP and MCP</p></li><li><p><strong>Open source everything</strong> to drive adoption</p></li></ol><p>The best part? Tools that already support MCP are halfway there. They know how to speak protocol&#8202;&#8212;&#8202;they just need to speak to each other.</p><h3>The Last Mile to the AI OS</h3><p>We have MCP connecting tools to AI. We just need UCP connecting tools to each other. Together, they form the nervous system of an AI Operating System.</p><p>Imagine opening any tool and having it instantly understand your entire project context. Imagine AI that can see not just what you&#8217;re asking, but everything you&#8217;ve done across all your tools. Imagine never losing context again.</p><p>That&#8217;s not science fiction&#8202;&#8212;&#8202;it&#8217;s one protocol away. We built bridges to AI. Now let&#8217;s build bridges between everything else.</p><p>The question is: who will be first to realize that UCP is the missing piece that makes everything connected?</p><div><hr></div><p><em>Would you use a protocol that let all your tools share context? What would you build if context could flow freely between everything?</em></p><div class="directMessage button" data-attrs="{&quot;userId&quot;:18923543,&quot;userName&quot;:&quot;Ali B&quot;,&quot;canDm&quot;:null,&quot;dmUpgradeOptions&quot;:null,&quot;isEditorNode&quot;:true}" data-component-name="DirectMessageToDOM"></div><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[AI-Driven Development: When Your Product Becomes the Prototype]]></title><description><![CDATA[Moved from Medium. Original Post Date: March 7th 2024.]]></description><link>https://www.ali-b.com/p/ai-driven-development-when-your-product</link><guid isPermaLink="false">https://www.ali-b.com/p/ai-driven-development-when-your-product</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:57:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!AN7f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the fast-paced world of startups, the traditional advice has always been to &#8220;validate before you build.&#8221; Entrepreneurs are often told to gauge interest through marketing websites and waitlists before diving deep into product development. While these methods provide valuable feedback, they can also lead to prolonged periods of speculation without tangible results. But what if there&#8217;s a more efficient way? What if you could build your entire product in just one month, effectively making your product the prototype?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AN7f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AN7f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png 424w, https://substackcdn.com/image/fetch/$s_!AN7f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png 848w, https://substackcdn.com/image/fetch/$s_!AN7f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png 1272w, https://substackcdn.com/image/fetch/$s_!AN7f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AN7f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png" width="800" height="800" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:800,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AN7f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png 424w, https://substackcdn.com/image/fetch/$s_!AN7f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png 848w, https://substackcdn.com/image/fetch/$s_!AN7f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png 1272w, https://substackcdn.com/image/fetch/$s_!AN7f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd04a4695-8610-47fe-a424-12c8a6077ff6_800x800.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Before the era of Generative AI (GenAI), I embarked on a journey to build an iOS mobile app called <a href="https://www.handstandquest.com/">Handstand Quest</a>. Developed with a modest investment of about 5 hours per week, this project stretched over four years in a traditional approach to product development, where the product evolved through stages from concept to launch.</p><p>However, my perspective on product development underwent a radical shift with the advent of ChatGPT, specifically the GPT-4 model. Leveraging this advanced AI model, I was able to create the full <a href="https://plans.quest/">Plan Quest</a> product in just one month. This wasn&#8217;t just rapid development; it was a complete overhaul of the traditional development cycle. For me, building has always been the most effective form of articulation, and with GPT-4, I could do it at speeds I never imagined possible.</p><blockquote><p><em>The whole world is obsessing over building AI products. I think the whole world should obsess about building their product with AI!</em></p></blockquote><p>Investing in a ChatGPT subscription was a game-changer, granting me access to the GPT-4 model&#8217;s capabilities. While I experimented with various AI tools, including Microsoft Copilot, Google Gemini, and GitHub Copilot, none offered the same level of efficiency and effectiveness as interacting directly with ChatGPT. It transformed my approach to coding, allowing me to modify, change, write, and create at an unprecedented pace. The product itself became the prototype, evolving in real-time based on the direct application of AI-driven insights and developments.</p><p>For those juggling multiple projects, ChatGPT&#8217;s ability to facilitate context switching is invaluable. It serves as a quick refresher on areas you haven&#8217;t touched for a while, seamlessly integrating into the development workflow.</p><p>This experience taught me an invaluable lesson about the power of AI in accelerating product development. The traditional barriers between ideation, prototyping, and product development blur when you can iterate at such speed. If you&#8217;re interested in a deeper dive into how AI can streamline the coding process, check out this <a href="https://medium.com/@alibadereddin/redefining-web-development-the-unbelievable-power-of-chatgpt-in-a-nextjs-react-app-edeb382508af">detailed walkthrough</a> I wrote for one of the features I was building.</p><p>For fellow entrepreneurs navigating the complexities of startup development, embracing AI tools like ChatGPT can transform your product development process. When your product becomes the prototype, you&#8217;re not just building; you&#8217;re iterating, learning, and refining at a pace that traditional methodologies cannot match.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[NextJS, Firebase, and Stripe Pricing Table Integration]]></title><description><![CDATA[Moving from Medium. Original Post Date: April 4th 2024.]]></description><link>https://www.ali-b.com/p/nextjs-firebase-and-stripe-pricing</link><guid isPermaLink="false">https://www.ali-b.com/p/nextjs-firebase-and-stripe-pricing</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:55:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!t66x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Introduction</h3><p>I wanted to incorporate payments into my existing NextJS + Firebase app (<a href="https://plans.quest">https://plans.quest</a>), primarily so that users could upgrade from a &#8220;Free&#8221; to a &#8220;Pro&#8221; subscription.</p><p>The first and only choice that came to mind is Stripe, given its reputation and brand strength.</p><p>I signed up for a Stripe account and logged in.</p><h3>Pricing Plans</h3><p>I was inspired by some pricing tables available on the web, for example, TypeForm. I realized later that this table UI was not built through Stripe&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!t66x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!t66x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png 424w, https://substackcdn.com/image/fetch/$s_!t66x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png 848w, https://substackcdn.com/image/fetch/$s_!t66x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png 1272w, https://substackcdn.com/image/fetch/$s_!t66x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!t66x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png" width="800" height="449" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:449,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!t66x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png 424w, https://substackcdn.com/image/fetch/$s_!t66x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png 848w, https://substackcdn.com/image/fetch/$s_!t66x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png 1272w, https://substackcdn.com/image/fetch/$s_!t66x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffffa6a1f-14b6-46b8-a598-7385b8056954_800x449.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">TypeForm Pricing Table</figcaption></figure></div><p>Anyways, I started in Stripe by exploring the Pricing Table.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wcHE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wcHE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png 424w, https://substackcdn.com/image/fetch/$s_!wcHE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png 848w, https://substackcdn.com/image/fetch/$s_!wcHE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png 1272w, https://substackcdn.com/image/fetch/$s_!wcHE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wcHE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png" width="800" height="264" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:264,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!wcHE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png 424w, https://substackcdn.com/image/fetch/$s_!wcHE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png 848w, https://substackcdn.com/image/fetch/$s_!wcHE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png 1272w, https://substackcdn.com/image/fetch/$s_!wcHE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92ed56cf-1f4d-48bf-9860-f90ca9abf8a6_800x264.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Stripe Pricing Table Editor</figcaption></figure></div><p>I found the UI to be simple and it really helped me structure my thinking about what a pricing plan would look like for my app. I was able to put together a pricing plan very quickly.</p><p>You basically add products, and per product you define prices and other settings like logo, features, etc&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ukvC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ukvC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png 424w, https://substackcdn.com/image/fetch/$s_!ukvC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png 848w, https://substackcdn.com/image/fetch/$s_!ukvC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png 1272w, https://substackcdn.com/image/fetch/$s_!ukvC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ukvC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png" width="800" height="572" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:572,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ukvC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png 424w, https://substackcdn.com/image/fetch/$s_!ukvC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png 848w, https://substackcdn.com/image/fetch/$s_!ukvC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png 1272w, https://substackcdn.com/image/fetch/$s_!ukvC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f81433-d5e8-4481-8f2c-e1defb763195_800x572.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">My App&#8217;s Pricing Table</figcaption></figure></div><p><em>Tip</em>: It was a bit tricky to figure out how to give users the choice to select between monthly or yearly plans, but then figured it was automatic as you add both the monthly and yearly prices to a product.</p><p><em>To save you time</em>: I recommend you first start in &#8220;Test Mode&#8221; in the Stripe UI, so you have the option to copy the products over into the &#8220;Live&#8221; mode.</p><p>It was also nice to see the ability to add a &#8220;Contact Us&#8221; option that would point to a custom link.</p><p><em>Warning (for later)</em>: I really hoped I could disable or remove the &#8220;Subscribe&#8221; button on my free &#8220;Starter&#8221; product, but there was no way to do that. This limitation alone creates an inconvenient and confusing experience for my users, so I guess the way forward is to either remove the &#8220;Free&#8221; tier, live with the weird experience, or skip using Pricing tables altogether.</p><h3>Integrating The Pricing Plan</h3><p>My next natural step was to try integrating the pricing plan into both my app and its marketing website.</p><h3>NextJS App Integration</h3><p>My app is built on NextJS, React, Vercel and Firebase. I introduced a menu item for the user to &#8220;View Plans&#8221;.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vtz8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vtz8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png 424w, https://substackcdn.com/image/fetch/$s_!Vtz8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png 848w, https://substackcdn.com/image/fetch/$s_!Vtz8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png 1272w, https://substackcdn.com/image/fetch/$s_!Vtz8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vtz8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png" width="290" height="222" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:222,&quot;width&quot;:290,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Vtz8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png 424w, https://substackcdn.com/image/fetch/$s_!Vtz8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png 848w, https://substackcdn.com/image/fetch/$s_!Vtz8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png 1272w, https://substackcdn.com/image/fetch/$s_!Vtz8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4142dd7d-e924-4819-a8ab-ec896737795d_290x222.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">User Menu in My App</figcaption></figure></div><p>On clicking &#8220;View Plans&#8221;, that same pricing table would show in a dialog. So far, easy.</p><pre><code>import React, { useState, useEffect } from 'react';
import { Dialog, DialogTitle, DialogContent } from '@mui/material';

const StripePricingTable = () =&gt; {
  useEffect(() =&gt; {
    const script = document.createElement("script");
    script.src = "https://js.stripe.com/v3/pricing-table.js";
    script.async = true;
    document.body.appendChild(script);

    return () =&gt; {
      document.body.removeChild(script);
    };
  }, []);

  return React.createElement("stripe-pricing-table", {
    "pricing-table-id": process.env.NEXT_PUBLIC_STRIPE_PRICING_TABLE_ID,
    "publishable-key": process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,
  });
};

const StripePlansDialog = ({ open, onClose }) =&gt; {
  return (
    &lt;Dialog open={open} onClose={onClose} fullWidth maxWidth="lg"&gt;
      &lt;DialogTitle&gt;View Plans&lt;/DialogTitle&gt;
      &lt;DialogContent&gt;
          &lt;StripePricingTable /&gt;
        }
      &lt;/DialogContent&gt;
    &lt;/Dialog&gt;
  );
};

export default StripePlansDialog;</code></pre><h3>Marketing Site Integration</h3><p>For my marketing site, I use <a href="https://gohugo.io/">Hugo</a>, a free framework that gives me the power of full source control and is totally free. The hosting is also free on Firebase Hosting.</p><p>Integrating the pricing table was very straightforward, just a matter of including the &lt;stripe-pricing-table&gt; <a href="https://www.webcomponents.org/introduction">web component</a> copied from Stripe.</p><pre><code>&lt;div id="pricing" class="w-full min-h-screen flex flex-col justify-center items-center bg-secondary-800"&gt;
    &lt;div class="self-center text-center w-full xl:w-1/2 px-4 mb-8"&gt;
        &lt;h2 class="font-bold tracking-widest text-gray-200 text-4xl mb-4"&gt;{{ $reg.Title }}&lt;/h2&gt;
        &lt;div class="font-light text-gray-400 text-xl"&gt;
            {{ $reg.Content }}
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="w-full rounded mt-8"&gt;
        &lt;div class="mb-5 bg-white"&gt; 
            &lt;br&gt;
        &lt;/div&gt;
        &lt;script async src="https://js.stripe.com/v3/pricing-table.js"&gt;&lt;/script&gt;
        &lt;stripe-pricing-table class="mt-8" pricing-table-id="prctbl_1OSQRJGUlyEIrGMQsRYJgv7e"
        publishable-key="pk_live_51H&#8230;"&gt;
        &lt;/stripe-pricing-table&gt;
    &lt;/div&gt;
    
    
    &lt;div class="flex flex-row w-full justify-center pt-6"&gt;
        &lt;a class="px-10 py-2 text-gray-200 bg-primary-700 rounded-full shadow-md text-lg hover:bg-secondary-800 hover:border-red" href="https://my.plans.quest/" target="_blank"&gt;Get Started-it is free&lt;/a&gt;
    &lt;/div&gt;
&lt;/div&gt;</code></pre><p><em>Warning (for later)</em>: Ok, so now that the pricing table is integrated on my marketing website, what happens when a user makes a purchase, and how do I tie that with my backend to know who is the user that made the purchase?</p><h3>Stripe Webhooks</h3><p>When certain events occur in Stripe, such as successful payments, subscription changes, or failed transactions, Stripe can send webhook events in the form of HTTP POST requests to a specified endpoint URL on your server.</p><p>This is what we&#8217;ll rely on to have our app &#8220;register&#8221; a subscription purchase. Basically:</p><ul><li><p>When a purchase is successful, I want to track that in my app so the user gets access to the &#8220;pro&#8221; features</p></li><li><p>When a user cancels a subscription, I want to revoke access to the &#8220;pro&#8221; features in my app</p></li></ul><p>I have the option to create my endpoint (the Stripe webhook) as a NextJS API, Firebase Function, or rely on the <a href="https://extensions.dev/extensions/stripe/firestore-stripe-payments">Stripe Firebase extension</a>. In this article, I&#8217;ll focus on the NextJS approach.</p><h3>NextJS Stripe Webhook</h3><p>Implementing Stripe webhooks in a Next.js 14 application to handle purchase completion, subscription changes, and cancellations involves a few steps.</p><p>We&#8217;ll basically set up API routes to handle webhook events and then update our Firestore database based on those events.</p><p>Let&#8217;s install both Stripe and Firebase admin libraries, along with the &#8220;micro&#8221; library to handle reading the raw request from Stripe and verifying its signature for security purposes. We&#8217;re working with payments here, so doing things securely is critical.</p><pre><code>npm install stripe firebase-admin micro</code></pre><p>Now, to the real deal, the Stripe Webhook API. Create a new file /pages/api/stripe/webhook.ts. Let&#8217;s start by just doing signature verification and logging the Stripe event type and its data.</p><pre><code>import { NextApiRequest, NextApiResponse } from 'next';
import Stripe from 'stripe';
import { buffer } from 'micro';


const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: '2023-10-16' });


export const config = {
   api: {
       bodyParser: false,
   },
};


const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) =&gt; {
   console.log('Received Stripe webhook');


   if (req.method === 'POST') {
       console.log('Processing POST request for Stripe webhook');


       const reqBuffer = await buffer(req);
       const sig = req.headers['stripe-signature'];


       let event;
       try {
           event = stripe.webhooks.constructEvent(
               reqBuffer.toString(),
               sig,
               process.env.STRIPE_WEBHOOK_SECRET
           );
       } catch (err) {
           console.error(`Webhook Error: ${err.message}`);
           res.status(400).send(`Webhook Error: ${err.message}`);
           return;
       }


       // Log the event type and metadata
       console.log(`Received Stripe event: ${event.type}`);


       if (event.data &amp;&amp; event.data.object) {
           console.log('Event data:', event.data.object);
       }


       res.status(200).json({ received: true });
   } else {
       res.setHeader('Allow', 'POST');
       res.status(405).end('Method Not Allowed');
   }
};


export default webhookHandler;</code></pre><h3>Linking Stripe to The Local Webhook</h3><p>Now that we have the webhook endpoint created in NextJS, let&#8217;s make sure our Stripe Pricing Plan in &#8220;test mode&#8221; is linked to our local NextJS endpoint we&#8217;ve just created.</p><p>To ensure that Stripe can communicate with our local Stripe webhook endpoint during development, we can use Stripe&#8217;s Command Line Interface (CLI). The Stripe CLI allows us to forward events from our Stripe account to our local development environment.</p><p>On the command line, let&#8217;s install <a href="https://stripe.com/docs/stripe-cli">Stripe CLI</a>. On Mac (use installation method based on your OS):</p><pre><code>brew install stripe/stripe-cli/stripe</code></pre><p>Grab the Test API key <a href="https://capture.dropbox.com/HPVehsUMdG6ieFvZ">from Stripe</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JWLR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JWLR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png 424w, https://substackcdn.com/image/fetch/$s_!JWLR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png 848w, https://substackcdn.com/image/fetch/$s_!JWLR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png 1272w, https://substackcdn.com/image/fetch/$s_!JWLR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JWLR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png" width="800" height="279" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:279,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!JWLR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png 424w, https://substackcdn.com/image/fetch/$s_!JWLR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png 848w, https://substackcdn.com/image/fetch/$s_!JWLR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png 1272w, https://substackcdn.com/image/fetch/$s_!JWLR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2d2213-6b89-4a5b-a827-834fb222e6e0_800x279.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Test API Key</figcaption></figure></div><p>Back to the command line:</p><pre><code>stripe login - api-key &lt;your copied secret&gt;</code></pre><p>Then forward Stripe webhook request locally:</p><pre><code>stripe listen - forward-to http://localhost:3000/api/stripe/webhook</code></pre><p>You should see something like this in the Webhooks section in Stripe&#8217;s Developers dashboard.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rfyE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rfyE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png 424w, https://substackcdn.com/image/fetch/$s_!rfyE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png 848w, https://substackcdn.com/image/fetch/$s_!rfyE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png 1272w, https://substackcdn.com/image/fetch/$s_!rfyE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rfyE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png" width="758" height="130" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:130,&quot;width&quot;:758,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rfyE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png 424w, https://substackcdn.com/image/fetch/$s_!rfyE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png 848w, https://substackcdn.com/image/fetch/$s_!rfyE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png 1272w, https://substackcdn.com/image/fetch/$s_!rfyE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe69fb3af-71fe-497a-9e36-e063c0bc0db2_758x130.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Local Webhook Listener</figcaption></figure></div><h3>Making a Purchase</h3><p>Now, make sure your NextJS server is up and running, and let&#8217;s go to the Stripe pricing table in &#8220;Test Mode&#8221;, make a purchase, and see what happens in our NextJS logs.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!n39D!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n39D!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png 424w, https://substackcdn.com/image/fetch/$s_!n39D!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png 848w, https://substackcdn.com/image/fetch/$s_!n39D!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png 1272w, https://substackcdn.com/image/fetch/$s_!n39D!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!n39D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png" width="800" height="573" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:573,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!n39D!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png 424w, https://substackcdn.com/image/fetch/$s_!n39D!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png 848w, https://substackcdn.com/image/fetch/$s_!n39D!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png 1272w, https://substackcdn.com/image/fetch/$s_!n39D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bd3b5ae-7572-4881-9d34-57ed61ec5973_800x573.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">My App&#8217;s Pricing Table in Test Mode</figcaption></figure></div><p>Click subscribe on the &#8220;Pro&#8221; plan or whatever you have setup in your pricing table.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lyeS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lyeS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png 424w, https://substackcdn.com/image/fetch/$s_!lyeS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png 848w, https://substackcdn.com/image/fetch/$s_!lyeS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png 1272w, https://substackcdn.com/image/fetch/$s_!lyeS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lyeS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png" width="800" height="691" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:691,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lyeS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png 424w, https://substackcdn.com/image/fetch/$s_!lyeS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png 848w, https://substackcdn.com/image/fetch/$s_!lyeS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png 1272w, https://substackcdn.com/image/fetch/$s_!lyeS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e27267b-ac83-49d2-8a5a-6a09173be562_800x691.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Checkout Page</figcaption></figure></div><p>Use the 4242424242424242 <a href="https://stripe.com/docs/testing">test credit card number</a>, any 3 digits for CVC, and any future expiry date. On clicking subscribe, payment should be successful.</p><p>Looking at the logs, here are the events emitted:</p><ol><li><p><strong>charge</strong>.<strong>succeeded</strong>: Occurs when a charge is successfully created.</p></li><li><p><strong>payment_method</strong>.<strong>attached</strong>: A payment method (like a credit card) is attached to a customer.</p></li><li><p><strong>customer</strong>.<strong>created</strong>: A new customer is created in Stripe.</p></li><li><p><strong>customer</strong>.<strong>updated</strong>: The customer&#8217;s information is updated.</p></li><li><p><strong>customer</strong>.<strong>subscription</strong>.<strong>created</strong>: A new subscription is created for the customer.</p></li><li><p><strong>customer</strong>.<strong>subscription</strong>.<strong>updated</strong>: The subscription is updated, which can happen for various reasons, like a change in plan.</p></li><li><p><strong>payment_intent</strong>.<strong>succeeded</strong>: The payment intent (for capturing payment) succeeds.</p></li><li><p><strong>payment_intent</strong>.<strong>created</strong>: A new payment intent is created.</p></li><li><p><strong>invoice</strong>.<strong>created</strong>: An invoice is generated for the subscription.</p></li><li><p><strong>invoice</strong>.<strong>finalized</strong>: The invoice is finalized and ready for payment.</p></li><li><p><strong>invoice</strong>.<strong>updated</strong>: The invoice is updated.</p></li><li><p><strong>invoice</strong>.<strong>paid</strong>: The invoice is paid.</p></li><li><p><strong>invoice</strong>.<strong>payment_succeeded</strong>: The payment for the invoice succeeds.</p></li><li><p><strong>checkout</strong>.<strong>session</strong>.<strong>completed</strong>: The checkout session is completed, typically indicating the whole process of subscribing is done.</p></li></ol><p>Our most interesting events are <strong>customer</strong>.<strong>subscription</strong>.<strong>created </strong>and<strong> checkout</strong>.<strong>session</strong>.<strong>completed.</strong></p><h3>Changing a Subscription</h3><p>If you go back to the pricing table and click subscribe, this time it will tell you that you&#8217;ve already made a purchase. I think I turned on a Stripe setting to enable this behavior. It will then send you a link over email to manage your subscription.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5H0w!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5H0w!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png 424w, https://substackcdn.com/image/fetch/$s_!5H0w!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png 848w, https://substackcdn.com/image/fetch/$s_!5H0w!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png 1272w, https://substackcdn.com/image/fetch/$s_!5H0w!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5H0w!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png" width="800" height="348" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:348,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5H0w!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png 424w, https://substackcdn.com/image/fetch/$s_!5H0w!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png 848w, https://substackcdn.com/image/fetch/$s_!5H0w!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png 1272w, https://substackcdn.com/image/fetch/$s_!5H0w!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08467145-0512-4fb6-9758-e0dda5794d2b_800x348.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Customer Portal&#8202;&#8212;&#8202;Subscription Change</figcaption></figure></div><p>Let&#8217;s update the plan. Let&#8217;s say I go from a &#8220;Pro&#8221; product to a &#8220;Free&#8221; product.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y8zX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y8zX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png 424w, https://substackcdn.com/image/fetch/$s_!y8zX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png 848w, https://substackcdn.com/image/fetch/$s_!y8zX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png 1272w, https://substackcdn.com/image/fetch/$s_!y8zX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y8zX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png" width="800" height="801" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:801,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y8zX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png 424w, https://substackcdn.com/image/fetch/$s_!y8zX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png 848w, https://substackcdn.com/image/fetch/$s_!y8zX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png 1272w, https://substackcdn.com/image/fetch/$s_!y8zX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524fd5ba-c155-4578-bc3e-50f2f2047a18_800x801.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Customer Portal&#8202;&#8212;&#8202;Updating Plan</figcaption></figure></div><p>When that happens, here are the events that get triggered (for informational purposes).</p><ul><li><p>customer.updated</p></li><li><p>customer.subscription.updated</p></li><li><p>invoice.created</p></li><li><p>invoice.finalized</p></li><li><p>invoice.paid</p></li><li><p>invoice.payment_succeeded</p></li><li><p>invoiceitem.created</p></li></ul><p>Most relevant event here is <strong>customer.subscription.updated</strong>.</p><h3>Canceling a Subscription</h3><p>Same steps as &#8220;changing plan&#8221;, but instead we &#8220;Cancel Plan&#8221;.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mlHn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mlHn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png 424w, https://substackcdn.com/image/fetch/$s_!mlHn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png 848w, https://substackcdn.com/image/fetch/$s_!mlHn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png 1272w, https://substackcdn.com/image/fetch/$s_!mlHn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mlHn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png" width="800" height="944" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63325467-5dba-4ccd-9349-54773568106a_800x944.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:944,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mlHn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png 424w, https://substackcdn.com/image/fetch/$s_!mlHn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png 848w, https://substackcdn.com/image/fetch/$s_!mlHn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png 1272w, https://substackcdn.com/image/fetch/$s_!mlHn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63325467-5dba-4ccd-9349-54773568106a_800x944.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Customer Portal&#8202;&#8212;&#8202;Cancelling Plan</figcaption></figure></div><p>On cancellation (pre-confirmation), here are the events that get triggered.</p><ul><li><p>customer.subscription.updated</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ebyk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ebyk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png 424w, https://substackcdn.com/image/fetch/$s_!Ebyk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png 848w, https://substackcdn.com/image/fetch/$s_!Ebyk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png 1272w, https://substackcdn.com/image/fetch/$s_!Ebyk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ebyk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png" width="800" height="743" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/02923231-5f7f-4212-8be0-9b006fc50040_800x743.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:743,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ebyk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png 424w, https://substackcdn.com/image/fetch/$s_!Ebyk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png 848w, https://substackcdn.com/image/fetch/$s_!Ebyk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png 1272w, https://substackcdn.com/image/fetch/$s_!Ebyk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02923231-5f7f-4212-8be0-9b006fc50040_800x743.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cancel Plan Reason</figcaption></figure></div><p>After confirming, we also get that same<strong> customer.subscription.updated</strong> event!</p><h3>Linking Stripe User to Firebase User</h3><p>Ok great. So how do I know which user made the purchase and accordingly flag that in my system?</p><p>Looking at the logs, I&#8217;ve noticed the user email is included in most of the event objects. Using the email as an identifier could work both in the Web App and from the marketing website, given that an email is provided when a user makes a purchase.</p><p>However, since Stripe does not enforce uniqueness of an email address per customer, I&#8217;m playing it safe like a typical developer, and as a result, will rely on the User ID from Firebase to link between the user in Firebase and the customer in Stripe. So how do I go about doing that?</p><p>Luckily, the &lt;stripe-pricing-table&gt; web component supports setting the <strong><a href="https://stripe.com/docs/payments/checkout/pricing-table#track-subscriptions">client-reference-id</a></strong> property. When the property is set, the pricing table passes it to the Checkout Session&#8217;s <strong><a href="https://stripe.com/docs/api/checkout/sessions/object#checkout_session_object-client_reference_id">client_reference_id</a></strong> attribute to help us reconcile the Checkout Session with our internal system.</p><p><em>Side Note</em>: Ok, so I&#8217;m deciding to drop the idea of using the &#8220;Pricing Table&#8221; for purchases on the Marketing website. It&#8217;s just not practical (no way to pass user id ). It would have been nice to let me just put it there for informational purposes without any buttons, but that&#8217;s not possible either.</p><p>I&#8217;ll focus on the integration of the pricing table in my web app. I&#8217;ll go ahead and funnel in the Google Firebase user id to the pricing table.</p><pre><code>import React, { useState, useEffect } from 'react';
import { Dialog, DialogTitle, DialogContent } from '@mui/material';


import logger from "@/lib/logger";


const StripePricingTable = ({ user }) =&gt; {
 useEffect(() =&gt; {
   const script = document.createElement("script");
   script.src = "https://js.stripe.com/v3/pricing-table.js";
   script.async = true;
   document.body.appendChild(script);


   return () =&gt; {
     document.body.removeChild(script);
   };
 }, []);


 logger.debug("StripePricingTable user.uid: ", user.uid);


 return React.createElement("stripe-pricing-table", {
   "pricing-table-id": process.env.NEXT_PUBLIC_STRIPE_PRICING_TABLE_ID,
   "publishable-key": process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,
   "client-reference-id": user.uid,
 });
};


const StripePlansDialog = ({ open, onClose, user }) =&gt; {
 return (
   &lt;Dialog open={open} onClose={onClose} fullWidth maxWidth="lg"&gt;
     &lt;DialogTitle&gt;View Plans&lt;/DialogTitle&gt;
     &lt;DialogContent&gt;
       &lt;StripePricingTable user={user} /&gt;
     &lt;/DialogContent&gt;
   &lt;/Dialog&gt;
 );
};


export default StripePlansDialog;</code></pre><p>Alright, so now that I am passing the user Id to the pricing table, when a user makes a purchase, I can see the value of the user Id getting logged in the <strong>checkout.session.completed</strong> event. Below is what the event object looks like with a good amount of the properties trimmed out since they are not very relevant. The property that matters to us is &#8220;client_reference_id&#8221;.</p><pre><code>Event data: {
  id: 'cs_test_...',
  amount_total: 8499,
  cancel_url: 'https://stripe.com',
  client_reference_id: 'ClHemjvo...',
  created: 1704244228,
  customer: 'cus_PIuqCn...',
  customer_creation: 'always',
  customer_details: {
    address: {
      city: null,
      country: 'US',
      line1: null,
      line2: null,
      postal_code: '12121',
      state: null
    },
    email: 'whatever@gmail.com',
    name: 'Whatever',
    phone: null,\
  },
  customer_email: 'whatever@gmail.com',
  locale: 'en',
  mode: 'subscription',
  payment_method_types: [ 'card' ],
  payment_status: 'paid',
  status: 'complete',
  subscription: 'sub_1OUJ0RGUlyEIrGMQb3J27Dh0',
}</code></pre><p>Ok, so I can access the Firebase User Id when the user completes the &#8220;Checkout Session&#8221;.</p><p><em>For context</em>: when you integrate Stripe into your website or application, a Checkout Session is created to handle the details of the payment process, from presenting payment options to finalizing the transaction.</p><p>Let&#8217;s get to our Stripe Webhook we&#8217;ve implemented in NextJS. It&#8217;s currently logging events. Let&#8217;s add to it the logic to pick the user Firebase Id from the <strong>checkout.session.completed</strong> event and log it.</p><p>Let&#8217;s define a new method called &#8220;processStripeEventData&#8221; and call it from our webhook, right after we log the event.</p><pre><code>await processStripeEventData(event);</code></pre><p>Let&#8217;s set a structure for processing events, where on the <strong>checkout.session.completed</strong>, we link Firebase User Id to Stripe customer Id, and for the 3 subscription events (created, updated, deleted), we &#8220;take note&#8221; of the user subscription change.</p><pre><code>const checkoutCompleteEvent = "checkout.session.completed";
const subscriptionEvents = [
   "customer.subscription.created",
   "customer.subscription.updated",
   "customer.subscription.deleted"
];


async function processStripeEventData(stripeEvent) {
   try {
       // Example of logging
       console.log("Processing stripe event", { id: stripeEvent.id, type: stripeEvent.type });


       // If the event is a checkout complete event, map account to customer
       if (stripeEvent.type === checkoutCompleteEvent) {
           await recordCustomerAccountMappings(stripeEvent);
       }


       // If the event is subscription related, update the account subscription
       if (subscriptionEvents.includes(stripeEvent.type)) {
           await recordAccountSubscriptionChange(stripeEvent);
       }


   } catch (err) {
       // Handle errors, possibly logging them to your database
       console.error("Error processing Stripe event:", err);


       // Here you would record the error in your database
   }
}


async function recordCustomerAccountMappings(stripeEvent) {
   console.log("Mapping customer accounts", { id: stripeEvent.id, type: stripeEvent.type });


   const { customer, client_reference_id } = stripeEvent.data.object;
   if (customer &amp;&amp; client_reference_id) {
       console.log("Mapping customer to account", { customer, client_reference_id });


       // Here you would update your database with the customer and account mapping
   }
}


async function recordAccountSubscriptionChange(stripeEvent) {
   console.log("Recording subscription change", { id: stripeEvent.id, type: stripeEvent.type });
}</code></pre><p>After making a test purchase, I could see the following in the logs, and this confirms that I was able to find the &#8220;link&#8221; between the Stripe Customer Id and Firebase User Id.</p><pre><code>Mapping customer to account {
  customer: 'cus_PJAfq&#8230;',
  client_reference_id: 'k1Vare&#8230;'
}</code></pre><h3>Data Model</h3><p>Now that I can tap into the information that I need from Stripe events, it&#8217;s good to think a little bit about how I want to store the data in Firestore.</p><p>In my app, I currently store user accounts in the &#8220;users&#8221; collection. If I take the simplest approach possible, I could add a new &#8220;stripeId&#8221; property to the user document, and another &#8220;subscription&#8221; property to represent the subscription that the user has.</p><p>There is one catch here though. I&#8217;ve noticed the <strong>customer.subscription.created</strong> event happens before the <strong>checkout</strong>.<strong>session</strong>.<strong>completed</strong> event. So I need to keep the subscription information somewhere before I &#8220;find&#8221; the link between the Stripe customer and the Firebase user. Wait, but that information is stored in Stripe anyways, so I still have a way to talk to Stripe to look it up.</p><h3>Firestore Database Setup</h3><p>In order to be able to talk to Firestore from NextJS, we need to make sure first we have the right configuration.</p><p>Install Firebase Admin SDK</p><pre><code>npm install firebase-admin</code></pre><p><strong>Generate a Firebase Service Account Key: </strong>Go to the Firebase Console. Select your project. Go to Project settings (gear icon near the top-left corner) &gt; Service accounts. Click on &#8220;Generate new private key&#8221; and confirm. This will download a JSON file with your service account credentials.</p><p>Go to Firestore in Firebase console, and copy the database url from the browser address bar (format should be https://console.firebase.google.com/u/0/project/&lt;project_Id&gt;/firestore)</p><p>Create the lib/firebaseAdmin.ts to initialize Firebase on the server side</p><pre><code>import admin from 'firebase-admin';


if (!admin.apps.length) {
 admin.initializeApp({
   credential: admin.credential.cert({
     projectId: process.env.FIREBASE_PROJECT_ID,
     clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
     privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'),
   }),
   databaseURL: process.env.FIREBASE_DATABASE_URL,
 });
}


export default admin;</code></pre><p>Make sure the environment variables are defined in your .env.local file.</p><h3>Updating Firestore Database</h3><p>Ok, now that we&#8217;ve set up Firebase integration on the backend, let&#8217;s listen to the Stripe events and make the database updates accordingly.</p><p>In the webhook.ts file, let&#8217;s reference the Firestore db object.</p><pre><code>import admin from '@/lib/firebaseAdmin';

const db = admin.firestore();</code></pre><p>Now, let&#8217;s update the recordCustomerAccountMappings function to write the stripeCustomerId property to the user document.</p><pre><code>async function recordCustomerAccountMappings(stripeEvent) {
   console.log("Mapping customer accounts", { id: stripeEvent.id, type: stripeEvent.type });


   const { customer: stripeCustomerId, client_reference_id: userId } = stripeEvent.data.object;
   if (stripeCustomerId &amp;&amp; userId) {
       console.log("Mapping customer to account", { stripeCustomerId, userId });


       const userRef = db.collection('users').doc(userId);


       try {
           await userRef.update({
               stripeId: stripeCustomerId
           });
          
           console.log("Mapped Stripe customer to user account", { userId, stripeCustomerId });
       } catch (err) {
           console.error("Error mapping Stripe customer to user account:", err);
           // Handle any errors here
       }
   }
}</code></pre><p>Given the fact that <strong>customer.subscription.created</strong> event happens before the <strong>checkout</strong>.<strong>session</strong>.<strong>completed</strong> event, when I map the two, I should go look for customer subscription data in Stripe and make sure I have that updated in the User document.</p><p>Let&#8217;s reference Stripe from webhook.ts</p><pre><code>import Stripe from 'stripe';


const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: '2023-10-16' });</code></pre><p>Let&#8217;s add a new method to be called from recordCustomerAccountMappings that pulls the Stripe customer existing subscriptions and maps it to what we want to know about at the end of the day: what active subscription does the user have!</p><pre><code>async function updateUserSubscriptionPlan(userRef, stripeCustomerId) {
   try {
       // Fetch the latest subscription for the user from Stripe
       const subscriptions = await stripe.subscriptions.list({
           customer: stripeCustomerId,
           status: 'active',
           limit: 1
       });


       const userSubscription = subscriptions.data[0];


       console.log("Fetched user subscription data", { userSubscription });


       if (userSubscription) {
           const planProductId = userSubscription.items.data[0].plan.product;


           console.log("Fetched user subscription plan ID", { planProductId });


           // Determine the plan type ("free" or "pro")
           const planType = (planProductId === 'prod_PI38VLrT5MjysO') ? 'pro' : 'free';


           // Update the user document with the subscription plan
           await userRef.update({ subscriptionPlan: planType });
           console.log("Updated user subscription data", { subscriptionPlan: planType });
       } else {
           // If there is no subscription, set the plan to "free"
           await userRef.update({ subscriptionPlan: 'free' });
           console.log("Updated user subscription data", { subscriptionPlan: 'free' });
       }


   } catch (err) {
       console.error("Error in updateUserSubscriptionPlan:", err);
       // Handle any errors here
   }
}</code></pre><p>Replace &#8216;prod_PI38VLrT5MjysO&#8217; with your product&#8217;s plan id (In Test mode).</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Auca!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Auca!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png 424w, https://substackcdn.com/image/fetch/$s_!Auca!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png 848w, https://substackcdn.com/image/fetch/$s_!Auca!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png 1272w, https://substackcdn.com/image/fetch/$s_!Auca!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Auca!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png" width="800" height="196" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:196,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Auca!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png 424w, https://substackcdn.com/image/fetch/$s_!Auca!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png 848w, https://substackcdn.com/image/fetch/$s_!Auca!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png 1272w, https://substackcdn.com/image/fetch/$s_!Auca!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F120edf5c-9bae-4e8a-934a-835b7bd342d9_800x196.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Product ID in Test Mode</figcaption></figure></div><p>Next, let&#8217;s update the recordAccountSubscriptionChange function to pick up the subscription state changes.</p><pre><code>async function recordAccountSubscriptionChange(stripeEvent) {
   console.log("Recording subscription change", { id: stripeEvent.id, type: stripeEvent.type });


   const { customer: stripeCustomerId, id: subscriptionId, status, plan } = stripeEvent.data.object;
   console.log("Subscription change data", { stripeCustomerId, subscriptionId, status, plan });


   try {
       const usersRef = db.collection('users');
       const querySnapshot = await usersRef.where('stripeId', '==', stripeCustomerId).get();


       if (querySnapshot.empty) {
           throw new Error(`User not found for Stripe customer ID ${stripeCustomerId}`);
       }


       const userRef = querySnapshot.docs[0].ref;


       // Call updateUserSubscriptionPlan to handle the subscription update
       await updateUserSubscriptionPlan(userRef, stripeCustomerId);


       console.log("Handled user subscription update", { stripeCustomerId });


   } catch (err) {
       console.error("Error in recordAccountSubscriptionChange:", err);
       // Handle any errors here
   }
}</code></pre><p>At this point, in theory, we should have all the changes we need to &#8220;sync&#8221; with Stripe on all the user payments and subscription changes.</p><p>Let&#8217;s test and make sure all the user actions map to the Firestore DB in the way we desire them to.</p><p>I just completed a purchase for a &#8220;Pro&#8221; subscription, and the User document has the <em><strong>stripeId</strong></em> updated but the subscriptionPlan is &#8220;pro&#8221;. Awesome!</p><p>I&#8217;ll then test out changing the plan from &#8220;Pro&#8221; to &#8220;Free&#8221; and then back from &#8220;Free&#8221; to &#8220;Pro&#8221;. Amazing, it works!</p><p>However, when I &#8220;cancel&#8221; the subscription, it is still considered &#8220;pro&#8221;. This is because on cancellation, the subscription will get scheduled to be canceled at the end of the billing period.</p><p>In order to simulate an actual cancellation, I&#8217;ll go ahead and delete the customer from Stripe (Go to <a href="https://dashboard.stripe.com/test/customers">customers</a>, select the user and delete). Now that it is done, the user&#8217;s subscription plan is &#8220;free&#8221;, which is exactly what I&#8217;d expect.</p><p>The &#8220;stripeId&#8221; field is still set on the User object. That&#8217;s fine, but I want to make sure that if the same Firebase user comes back and makes a purchase, a new customer id is generated and updated in the User&#8217;s document. And it&#8217;s just what I expected, awesome!</p><h3>Check User Subscription Status</h3><p>When a user has purchased the &#8220;pro&#8221; plan, the property <em>subscriptionPlan</em> in the users/{userId} doc in Firestore will be set to &#8220;pro&#8221;.</p><p>The first thing I want to change in my app is the user menu. It currently shows a &#8220;View Plan&#8221; that when clicked will show the pricing table. If the user has already purchased the &#8220;pro&#8221; plan, I want to hide that option and show a &#8220;Manage Plan&#8221; menu item, that when clicked takes the user directly to the Stripe Customer Portal.</p><p>To make the access to the &#8220;pro&#8221; status reusable in my app, I will define a React hook under lib/hooks/useSubscriptionStatus to return a boolean whether the user has the pro plan or not.</p><pre><code>import { useState, useEffect } from 'react';
import { getFirestore, doc, onSnapshot } from 'firebase/firestore';


const useSubscriptionStatus = (userId: string) =&gt; {
 const [hasProPlan, setHasProPlan] = useState(false);
 const firestore = getFirestore();


 useEffect(() =&gt; {
   if (!userId) return; // Ensure there is a userId before proceeding


   // Reference to the specific user document
   const userRef = doc(firestore, 'users', userId);


   // Listen for changes in real-time
   const unsubscribe = onSnapshot(userRef, (documentSnapshot) =&gt; {
     if (documentSnapshot.exists()) {
       // Check the 'subscriptionPlan' field to determine if the user has a 'pro' plan
       const userData = documentSnapshot.data();
       const subscriptionPlan = userData.subscriptionPlan;
       setHasProPlan(subscriptionPlan === 'pro');
     } else {
       // Handle the case where the document does not exist
       setHasProPlan(false);
     }
   });


   // Cleanup listener on unmount
   return () =&gt; unsubscribe();
 }, [userId, firestore]);


 return hasProPlan;
};


export default useSubscriptionStatus;</code></pre><p>When the user clicks on &#8220;Manage Plan&#8221;, I want to route them to the <a href="https://stripe.com/docs/customer-management/activate-no-code-customer-portal">Stripe Customer Portal</a>. According to Stripe documentation, we can use a prefilled_email URL parameter in the query string of our login link URL to streamline the login experience.</p><p>Example login link: </p><p>https://billing.stripe.com/p/login/test_4gw6oJchs69w47e7ss?prefilled_email=jenny%40example.com</p><p>In my React component, I reference the React hook and within the component I retrieve the boolean that tells whether the user has a Pro plan.</p><pre><code>import useSubscriptionStatus from '@/lib/hooks/useSubscriptionStatus';

const hasProPlan = useSubscriptionStatus(user?.uid);</code></pre><p>Then accordingly, I display &#8220;Manage Plan&#8221; or &#8220;View Plans&#8221;.</p><pre><code>{hasProPlan ? (
 &lt;StyledMenuItem onClick={handleManagePlan}&gt;
   &lt;ListItemIcon&gt;
     &lt;SettingsIcon fontSize="small" /&gt;
   &lt;/ListItemIcon&gt;
   Manage Plan
 &lt;/StyledMenuItem&gt;
) : (
 &lt;StyledMenuItem onClick={handleViewPlans}&gt;
   &lt;ListItemIcon&gt;
     &lt;ViewListIcon fontSize="small" /&gt;
   &lt;/ListItemIcon&gt;
   View Plans
 &lt;/StyledMenuItem&gt;
)}</code></pre><p>And here is the logic for managing the plan. I got the <a href="https://dashboard.stripe.com/test/settings/billing/portal">portal url from Stripe</a> and stored it as an environment variable given that there are separate links for Test vs Live modes..</p><pre><code>const handleManagePlan = () =&gt; {
 // Get the base URL from the environment variable
 const portalBaseUrl = process.env.NEXT_PUBLIC_STRIPE_CUSTOMER_PORTAL_BASE_URL;


 if (!portalBaseUrl) {
   console.error("Stripe Customer Portal URL is not set.");
   // Handle the error appropriately
   return;
 }


 // Construct the URL
 const portalUrl = user?.email
   ? `${portalBaseUrl}?prefilled_email=${encodeURIComponent(user.email)}`
   : portalBaseUrl;


 // Open the URL in a new window/tab
 window.open(portalUrl, '_blank');
};</code></pre><h3>Launching to Production</h3><h4>Environment Variables &amp; NextJS Vercel Deployment</h4><p>Since I am using Vercel, which by the way, is the best platform I&#8217;ve ever seen for simplified CI/CD, going to production will be as simple as merging my code into the main branch and <a href="https://vercel.com/docs/projects/environment-variables">adding</a> the new environment variables.</p><p>For a refresher, below is the list of environment variables that need to be defined.</p><h4>Firebase</h4><p>Go to the Firebase Console, select your project, go to Project settings (gear icon near the top-left corner) &gt; Service accounts, and if you have not already done so, click on &#8220;Generate new private key&#8221; and confirm. This will download a JSON file with your service account credentials. Take those values from the JSON file and set them for the following environment variables.</p><ul><li><p><strong>FIREBASE_PROJECT_ID</strong></p></li><li><p><strong>FIREBASE_CLIENT_EMAIL</strong></p></li><li><p><strong>FIREBASE_PRIVATE_KEY</strong></p></li></ul><p>For the <strong>FIREBASE_DATABASE_URL</strong> environment variable, go to Firestore in Firebase console, and copy the database url from the browser address bar (format should be <a href="https://console.firebase.google.com/u/0/project/">https://console.firebase.google.com/u/0/project/</a>&lt;project_Id&gt;/firestore).</p><h4>Stripe</h4><ul><li><p><strong>NEXT_PUBLIC_STRIPE_PRICING_TABLE_ID</strong>: get it from pricing table code snippet at /pricing-tables in Stripe dashboard.</p></li><li><p><strong>NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY</strong>: get it from pricing table code snippet at /pricing-tables in Stripe dashboard.</p></li><li><p><strong>NEXT_PUBLIC_STRIPE_CUSTOMER_PORTAL_BASE_URL</strong>: From settings/billing/portal in Stripe dashboard.</p></li><li><p><strong>STRIPE_WEBHOOK_SECRET</strong>: from /webhooks in Stripe dashboard.</p></li></ul><h4>Stripe Webhook Staging &amp; Production Endpoints Setup</h4><p>After deployment of all our changes to the staging environment, let&#8217;s point the Stripe Hosted Endpoint for webhooks in the Stripe Dashboard to the NextJS API endpoint in the staging environment.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!j_pT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j_pT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png 424w, https://substackcdn.com/image/fetch/$s_!j_pT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png 848w, https://substackcdn.com/image/fetch/$s_!j_pT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png 1272w, https://substackcdn.com/image/fetch/$s_!j_pT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j_pT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png" width="800" height="923" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:923,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!j_pT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png 424w, https://substackcdn.com/image/fetch/$s_!j_pT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png 848w, https://substackcdn.com/image/fetch/$s_!j_pT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png 1272w, https://substackcdn.com/image/fetch/$s_!j_pT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a5a8749-c3ed-4bb7-8baf-3d17245c81bb_800x923.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Adding Webhook Endpoint in Stripe</figcaption></figure></div><p>Point to the endpoint and make sure to select the relevant events we are listening to. After adding the endpoint, copy the secret into the staging environment STRIPE_WEBHOOK_SECRET environment variable.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_nOv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_nOv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png 424w, https://substackcdn.com/image/fetch/$s_!_nOv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png 848w, https://substackcdn.com/image/fetch/$s_!_nOv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png 1272w, https://substackcdn.com/image/fetch/$s_!_nOv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_nOv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png" width="800" height="251" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:251,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_nOv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png 424w, https://substackcdn.com/image/fetch/$s_!_nOv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png 848w, https://substackcdn.com/image/fetch/$s_!_nOv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png 1272w, https://substackcdn.com/image/fetch/$s_!_nOv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02484cca-166d-482b-bd7c-17a176e44a5c_800x251.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Grabbing Stripe Webhook Signing Secret</figcaption></figure></div><p>One interesting thing is that you will need to re-deploy in staging after adding a new environment variable, and when you re-deploy in Vercel in staging, a new subdomain url is generated. Instead of adding a new endpoint in Stripe, just go and update the current endpoint.</p><p>Now, let&#8217;s go to the staging environment and make sure everything works as expected.</p><p>You should start seeing events funneling in. But for some reason, my NextJS endpoint hosted on the Vercel staging environment was returning an HTTP 401 (Unauthorized) response.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nKK7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nKK7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png 424w, https://substackcdn.com/image/fetch/$s_!nKK7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png 848w, https://substackcdn.com/image/fetch/$s_!nKK7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png 1272w, https://substackcdn.com/image/fetch/$s_!nKK7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nKK7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png" width="800" height="257" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:257,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nKK7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png 424w, https://substackcdn.com/image/fetch/$s_!nKK7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png 848w, https://substackcdn.com/image/fetch/$s_!nKK7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png 1272w, https://substackcdn.com/image/fetch/$s_!nKK7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2935ca70-30d6-4e4f-8777-9037debb6175_800x257.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Stripe Webhook Events</figcaption></figure></div><p>Looking at the Function logs in Vercel, there really wasn&#8217;t much being logged, not even the &#8216;Received Stripe webhook&#8217; I logged at the very start of the webhook handler.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ygYG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ygYG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png 424w, https://substackcdn.com/image/fetch/$s_!ygYG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png 848w, https://substackcdn.com/image/fetch/$s_!ygYG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png 1272w, https://substackcdn.com/image/fetch/$s_!ygYG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ygYG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png" width="800" height="333" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a579432a-f412-4c17-972a-be232b7a40f3_800x333.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:333,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ygYG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png 424w, https://substackcdn.com/image/fetch/$s_!ygYG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png 848w, https://substackcdn.com/image/fetch/$s_!ygYG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png 1272w, https://substackcdn.com/image/fetch/$s_!ygYG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa579432a-f412-4c17-972a-be232b7a40f3_800x333.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Vercel Function Logs</figcaption></figure></div><p>Wondering if this is some Vercel staging crap I am dealing with, I decided to add the production endpoint in Stripe for the webhook (make sure you are not in Test mode), pull the STRIPE_WEBHOOK_SECRET and add the environment variable for production, then merge to the main branch to kick deployment to production.</p><p>Testing in production, I got a 400 Bad Request, but at least it&#8217;s some useful error message I could do something about.</p><p>Webhook Error: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?</p><p>Learn more about webhook signing and explore webhook integration examples for various frameworks at <a href="https://github.com/stripe/stripe-node#webhook-signing">https://github.com/stripe/stripe-node#webhook-signing</a></p><p>I started thinking, maybe the Production deployment didn&#8217;t pick up the STRIPE_WEBHOOK_SECRET environment variable that I&#8217;ve set. So I just validated it was set correctly and redeployed.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dj7x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dj7x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png 424w, https://substackcdn.com/image/fetch/$s_!dj7x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png 848w, https://substackcdn.com/image/fetch/$s_!dj7x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png 1272w, https://substackcdn.com/image/fetch/$s_!dj7x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dj7x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png" width="800" height="291" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:291,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dj7x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png 424w, https://substackcdn.com/image/fetch/$s_!dj7x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png 848w, https://substackcdn.com/image/fetch/$s_!dj7x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png 1272w, https://substackcdn.com/image/fetch/$s_!dj7x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d8d33f4-c1fc-445b-9b79-8ff108ea7aeb_800x291.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Stripe Production Webhook Events</figcaption></figure></div><p>And yes, a good kind of magic started happening.</p><p>One last catch, I realized hard coding caused a broken purchase experience in production.</p><pre><code>// Determine the plan type ("free" or "pro")
const planType = (planProductId === 'prod_PI38VLrT5MjysO') ? 'pro' : 'free';</code></pre><p>So I made sure the PRO Plan Product ID is also an environment variable.</p><pre><code>const planType = (planProductId === process.env.NEXT_PUBLIC_STRIPE_PRO_PLAN_PRODUCT_ID) ? 'pro' : 'free';</code></pre><h3>Conclusion</h3><p>The key takeaway from this experience is the importance of starting in &#8220;Test Mode&#8221; in Stripe, which allows for a smoother transition to &#8220;Live&#8221; mode. Additionally, the limitations encountered, such as the inability to modify certain aspects of the pricing table, impacted the effectiveness of my app&#8217;s payment user experience.</p><p>For developers embarking on a similar path, my advice is to pay close attention to the details of integration, especially when it comes to linking Stripe&#8217;s payment functionalities with your app&#8217;s user management system. The use of Stripe webhooks is crucial for tracking subscription statuses and reflecting these changes in your app. Also, consider not using the Pricing table to have more flexibility in your payment UI.</p><p>Finally, I have some recommendations to the Stripe team:</p><ol><li><p>Since you allow the user to pass the &#8220;client-reference-id&#8221; to the pricing table, consider storing that into the Customer object in Stripe and automatically detecting the plan that the user has subscribed to when rendering the pricing table.</p></li><li><p>Currently, you only allow one product to have a custom link. In my case, I had free, pro and pioneer plans. I only wanted the user to make a &#8220;purchase&#8221; on the &#8220;pro&#8221; plan, to contact me on the &#8220;pioneer&#8221; plan and to either &#8220;Donate&#8221; on the &#8220;free&#8221; plan or just not have a button there at all.</p></li><li><p>On my marketing website, I thought it would be a good idea to include the pricing table. However, I later realized that exposing the &#8220;Subscribe&#8221; buttons on the marketing website from the pricing table would have the user purchase without being logged in. That&#8217;s fine if we could rely on emails to link accounts, but it turns out Stripe does not enforce unique emails. For new Stripe accounts, it would be nice to enforce unique emails by default, and then let your customers change that if needed.</p></li><li><p>Since I already put the effort into building the pricing table, it would have been really nice if I were able to expose it on the marketing website in &#8220;Info&#8221; mode, where there are either no buttons, or full ability to customize the link in all the buttons.</p></li><li><p>Seeing all the Stripe Webhook events was overwhelming. I didn&#8217;t know which ones I should really care about. It would be nice to have &#8220;contextual&#8221; documentation based on the structure of the pricing plan, from which you would recommend the most relevant events to listen to. In my case, there were only 4 events.</p></li><li><p>I created the pricing table in production mode first, then had to re-create everything in Test mode. Although there is an option to copy a product from Test mode to Live mode, there is no option to copy the Pricing table. It would be nice to be able to copy from Test to Live and Live to Test both products and pricing tables.</p></li><li><p>There are so many secrets and IDs to pick from different parts of the UI and plug them into environment variables. It would be nice if that process is streamlined a bit more.</p></li></ol><p>Some random bugs I&#8217;ve experienced:</p><ol><li><p>The &#8220;Continue&#8221; button was disabled in the pricing table because some field was missing. It was not visible in the UI why the &#8220;Continue&#8221; button was disabled, so I thought it&#8217;s an issue in the pricing table itself.</p></li><li><p>In the webhook endpoint description, you cannot type &#8220; &#8220; (space key) in the keyboard! I literally thought my keyboard space key was not working.</p></li></ol><p>In closing, I hope these suggestions serve as constructive feedback for the Stripe team. My experience integrating Stripe&#8217;s pricing table has been both challenging and rewarding, and I believe these enhancements could further streamline the process for developers like myself. I look forward to seeing how Stripe evolves and adapts to these suggestions, and I am excited about the prospect of even more seamless integrations in the future.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Overcoming Next.js Vercel Timeout With Firebase Functions]]></title><description><![CDATA[Moved from Medium. Original Post Date: May 2nd 2023.]]></description><link>https://www.ali-b.com/p/overcoming-nextjs-vercel-timeout</link><guid isPermaLink="false">https://www.ali-b.com/p/overcoming-nextjs-vercel-timeout</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:53:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!0urC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my current <a href="https://catalog.handstandquest.com/">Next.js web app</a>, I have two API endpoints:</p><ol><li><p>/api/generateExerciseData, which calls OpenAI API with gpt-3.5-turbo to generate exercise descriptions, categories, subcategories, intensities, and tips.</p></li><li><p>/api/generateWorkout, which calls OpenAI API with gpt-4 to generate workouts based on user prompts.</p></li></ol><p>While these endpoints work seamlessly in my local environment, they encounter issues in the Vercel production environment due to the ten-second <a href="https://vercel.com/docs/concepts/limits/overview#general-limits">Serverless Function Execution Timeout</a>.</p><p>I could upgrade from the Hobby plan to the Pro plan for $20/month to increase the timeout to 60 seconds, but the GPT-4 endpoint may take up to two minutes to run. Additionally, I&#8217;m reluctant to spend $240/year just for this single feature.</p><p>Furthermore, I have an existing <a href="https://www.handstandquest.com/home">mobile app</a> that I would like to integrate with those capabilities at some point in the future.</p><p>Considering the requirements above, I have decided to migrate my API endpoints from <a href="https://vercel.com/docs/concepts/functions/serverless-functions">Vercel Serverless Functions</a> to <a href="https://firebase.google.com/docs/functions">Firebase Cloud Functions</a>.</p><p>In this article, I will guide you through overcoming Vercel&#8217;s Serverless Function Execution Timeout limitation by replacing them with cost-effective Firebase Cloud Functions.</p><h3>Creating Firebase Cloud Functions</h3><h4>Initialization</h4><p>Install Firebase CLI and initialize Cloud Functions in your project:</p><pre><code>npm install -g firebase-tools
firebase login
firebase init functions</code></pre><p>The <code>firebase init functions</code> command initializes Firebase Cloud Functions in your project. This command configures and files to create and deploy serverless functions using Firebase.</p><p><strong>Note</strong>: I ran it on my existing Next.js code repository, but I recommend starting a new repository for the Firebase functions.</p><p><strong>Edit</strong>: I did end up deciding to move the functions to their own repostiroy to fully separate Vercel from Firebase, especially deployments and configs.</p><p>When you run <code>firebase init functions</code>, the Firebase CLI guides you through an interactive setup process:</p><ol><li><p>It asks you to select the Firebase project you want to associate with your functions.</p></li><li><p>It prompts you to choose your preferred language for writing functions (JavaScript or TypeScript). I chose TypeScript.</p></li><li><p>It creates a <code>functions</code> folder in your project&#8217;s root directory, which will contain all the necessary files and configurations for your Cloud Functions.</p></li><li><p>It generates a <code>package.json</code> file and a <code>node_modules</code> folder inside the <code>functions</code> directory, including the required dependencies for your functions.</p></li><li><p>If you choose TypeScript, it also sets up a <code>tsconfig.json</code> file to configure TypeScript compilation.</p></li></ol><p>After running <code>firebase init functions</code>, you can start developing your Firebase Cloud Functions by adding your code to the <code>index.js</code> (or <code>index.ts</code> for TypeScript) file inside the <code>functions</code> folder. Once you have written your functions, you can deploy them using the <code>firebase deploy&#8202;&#8212;&#8202;only functions</code> command.</p><h3>Creating the Functions</h3><p>Next, create the new functions inside the <code>functions</code> directory (created during initialization). For example, in <code>functions/index.ts</code>:</p><pre><code>import * as functions from "firebase-functions";


exports.generateExerciseData = functions.https.onRequest(async (req, res) =&gt; {
 res.send("Generates exercise data by calling OpenAI with gpt-3.5-turbo");
});


exports.generateWorkout = functions.https.onRequest(async (req, res) =&gt; {
 res.send("Generates workouts by calling OpenAI with gpt-4");
});</code></pre><p>For my own functions, I copied and pasted the code and the imports from my existing Next.js APIs. I got several errors from Firebase <a href="https://eslint.org/">ESLint</a> rules, and fixing them got so annoying and counterproductive, so I just ended up disabling the rules by setting <code>strict</code> to <code>false</code> in the <code>tsconfig.json</code> file in the <code>functions</code> folder.</p><h3>Testing the Functions Locally</h3><p>We can use the Firebase Emulator Suite to test the Firebase Cloud Functions locally. Here&#8217;s how to set it up and run your functions locally:</p><p>Navigate to your project&#8217;s root directory and set up the emulators:</p><pre><code>firebase init emulators</code></pre><p>When prompted, select &#8220;Functions&#8221; and follow the prompts to set up the Functions Emulator. Start the Firebase Emulator Suite:</p><pre><code>firebase emulators:start</code></pre><p>This will start the emulators, including the Functions Emulator.</p><p>Call your function locally using a tool like curl or Postman. Use the URL provided in the emulator output (e.g., http://localhost:5001/&lt;your-project-id&gt;/us-central1/&lt;function-name&gt;).</p><h3>Functions Emulator Troubleshooting</h3><p>On running the <code>firebase emulators:start</code> command, I got an error:</p><blockquote><p>functions: Failed to load function definition from source: FirebaseError: There was an error reading functions/package.json:</p><p>functions/lib/index.js does not exist, can&#8217;t deploy Cloud Functions</p></blockquote><p>The Firebase Functions emulator cannot find the required <code>index.js</code> file in the <code>functions/lib</code> directory. I missed building the TypeScript functions before starting the emulator. You can run the build command in the <code>functions</code> directory with this code:</p><pre><code>cd functions
npm run build</code></pre><p>This will transpile the TypeScript code to JavaScript and output it in the <code>functions/lib</code> directory. Once the build process is complete, start the Firebase emulators again:</p><pre><code>firebase emulators:start</code></pre><p>I saw this warning, so I updated the <code>package.json</code> to point to Node 18 rather than 16.</p><blockquote><p>functions: Your requested &#8220;node&#8221; version &#8220;16&#8221; doesn&#8217;t match your global version &#8220;18&#8221;. Using node@18 from host.</p></blockquote><p>Now, the Functions emulator started without issues.</p><p>I ran the following <code>curl</code> command to test one of the functions:</p><pre><code>curl -X POST -H "Content-Type: application/json" -d '{"userPrompt": "I want something basic that can help me get comfortable upside down with some wall assistance.", "exerciseList": "do your magic"}' http://127.0.0.1:5001/handstand-quest/us-central1/generateWorkout</code></pre><p>I got this response.</p><pre><code>{"error":"Request failed with status code 401"}</code></pre><p>The error &#8220;Request failed with status code 401&#8221; indicates the request is unauthorized.</p><h3>Firebase vs Next.js Environment Variables</h3><p>When I copied the code earlier, this is how I pulled the API key from OpenAI as an environment variable.</p><pre><code>const configuration = new Configuration({
 apiKey: process.env.NEXT_PUBLIC_OPENAI_API_KEY,
});</code></pre><p>Firebase functions have a different way of handling environment variables than Next.js. I had to use Firebase&#8217;s environment configuration to set environment variables for the Firebase functions.</p><p>To set the environment variable for the Firebase project, I ran the following command in the terminal:</p><pre><code>firebase functions:config:set openai.api_key="your_openai_api_key"</code></pre><p>I got this output, but I did not deploy it yet since I am still testing locally.</p><blockquote><p>&#10004; Functions config updated.</p><p>Please deploy your functions for the change to take effect by running firebase deploy&#8202;&#8212;&#8202;only functions</p></blockquote><p>In the Firebase function, I accessed this environment variable using <code>functions.config()</code> like this:</p><pre><code>const apiKey = functions.config().openai.api_key;</code></pre><p>I rebuilt the Firebase functions code and started the emulator again, and now I saw this error:</p><blockquote><p>Failed to load function definition from source: FirebaseError: Failed to load function definition from source: Failed to generate manifest from function source: TypeError: Cannot read properties of undefined (reading &#8216;api_key&#8217;)</p></blockquote><h3>Deploying the Functions</h3><p>I thought maybe I should deploy and check if Firebase &#8220;local&#8221; emulator would now pick up the environment variable.</p><pre><code>firebase deploy - only functions</code></pre><p>On deployment, I received the following errors.</p><blockquote><p>/Users/alib/Code/GitHub/hq-exercise-catalog/functions/lib/index.js</p><p>4:1 error Parsing error: The keyword &#8216;const&#8217; is reserved</p><p>/Users/alib/Code/GitHub/hq-exercise-catalog/functions/src/index.ts</p><p>1:1 error Parsing error: The keyword &#8216;import&#8217; is reserved</p><p>&#10006; 2 problems (2 errors, 0 warnings)</p></blockquote><p>The ESLint configuration was not recognizing the ES6 syntax. I updated the ESLint configuration to support ES6 syntax by following these steps to fix this.</p><p>First, ensure you have the following packages installed:</p><pre><code>npm install - save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin</code></pre><p>Create or update the <code>.eslintrc.js</code> file in the root of your project with the following content:</p><pre><code>module.exports = {
  parser: '@typescript-eslint/parser',
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
  },
  rules: {
    // Add any custom rules here
  },
};</code></pre><p>This configuration sets up ESLint to use the TypeScript parser and apply the recommended rules for TypeScript. After making these changes, the ESLint configuration should recognize the ES6 syntax and not throw errors related to the <code>const</code> and <code>import</code> keywords.</p><p>However, I was still getting the following error on the <code>.eslintrc.js</code> file:</p><blockquote><p>&#8216;module&#8217; is not defined.</p></blockquote><p>It appears the <code>module</code> keyword is causing an issue with the ESLint configuration. To fix this, I replaced the .js file with a .eslintrc.json file with the following content:</p><pre><code>{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module"
  },
  "rules": {
    // Add any custom rules here
  }
}</code></pre><p>On deployment, I got an even larger list of errors (summarized below):</p><blockquote><p>/Users/alib/Code/GitHub/hq-exercise-catalog/functions/lib/index.js</p><p>2:23 error &#8216;exports&#8217; is not defined no-undef</p><p>5:18 error Require statement not part of import statement @typescript-eslint/no-var-requires</p><p>5:18 error &#8216;require&#8217; is not defined no-undef</p><p>29:44 error &#8216;setTimeout&#8217; is not defined no-undef</p><p>131:5 error &#8216;console&#8217; is not defined no-undef</p><p>&#10006; 12 problems (12 errors, 0 warnings)</p></blockquote><p>Can you imagine how much time was wasted because of ESLint? Anyways, I updated the config once more:</p><pre><code>{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module"
  },
  "env": {
    "node": true
  },
  "rules": {
    "@typescript-eslint/no-var-requires": "off",
    "no-console": "off"
  }
}</code></pre><p>OK, it seems happy with the deployment now. Well, at least the ESLinting part. To sum up the deployment logs, there was this lingering issue in it:</p><blockquote><p>Could not load the function, shutting down.</p><p>Please visit <a href="https://cloud.google.com/functions/docs/troubleshooting">https://cloud.google.com/functions/docs/troubleshooting</a> for in-depth troubleshooting documentation.</p><p>Function failed on loading user code. This is likely due to a bug in the user code. Error message: Provided module can&#8217;t be loaded.</p><p>Did you list all required modules in the package.json dependencies?</p><p>Detailed stack trace: Error: Cannot find module &#8216;openai&#8217;</p></blockquote><p>Oops, I forgot to update the <code>packages.json</code> file. I am wondering how the <code>npm run build</code> passed! Anyways, I added the dependency, did <code>npm install</code> and <code>npm run build</code>, then deployed again. Finally, it succeeded.</p><blockquote><p>Function URL (generateExerciseData(us-central1)): <a href="https://us-central1-handstand-quest.cloudfunctions.net/generateExerciseData">https://us-central1-handstand-quest.cloudfunctions.net/generateExerciseData</a></p><p>Function URL (generateWorkout(us-central1)): <a href="https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout">https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout</a></p><p>&#10004; Deploy complete!</p><p>Project console: <a href="https://console.firebase.google.com/project/handstand-quest/overview">https://console.firebase.google.com/project/handstand-quest/overview</a></p></blockquote><p>Now, I want to get back to the local environment testing to ensure things work as expected. I started the emulator and then re-ran the <code>curl </code>command.</p><p>I still got the same error in the emulator.</p><blockquote><p>Failed to load function definition from source: FirebaseError: Failed to load function definition from source: Failed to generate manifest from function source: TypeError: Cannot read properties of undefined (reading &#8216;api_key&#8217;)</p></blockquote><p>This is when I realized that &#8220;deployment&#8221; is not related to the local environment. Common sense, but sometimes, I don&#8217;t have that.</p><h3>Local Firebase Env Variables</h3><p>It turns out the environment variables need to be fed to the emulator via a config file.</p><p>Fetch the current environment configuration and save it as a JSON file:</p><pre><code>firebase functions:config:get &gt; .runtimeconfig.json</code></pre><p>This command will create a <code>.runtimeconfig.json</code> file in your <code>functions</code> directory. Add this file to your .gitignore to prevent sensitive data from being committed to your repository.</p><p>Finally, it&#8217;s all working when the emulator starts. I reran my <code>curl</code> command from the terminal:</p><pre><code>curl -X POST -H "Content-Type: application/json" -d '{"userPrompt": "I want something basic that can help me get comfortable upside down with some wall assistance.", "exerciseList": "do your magic"}' http://127.0.0.1:5001/handstand-quest/us-central1/generateWorkout</code></pre><p>It&#8217;s working the way I expect!</p><h3>Replacing Next.js APIs with Firebase Functions</h3><p>Now that we&#8217;ve set up the Firebase functions and tested them locally for functionality, it&#8217;s time to update the Next.js application to call the Firebase Cloud Function instead of the Vercel API endpoint.</p><p>The Firebase Cloud Function URL will have the following format:</p><pre><code>https://&lt;region&gt;-&lt;project-id&gt;.cloudfunctions.net/&lt;function-name&gt;</code></pre><p>In my case, for one of my functions, this looks like this:</p><pre><code>https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout</code></pre><p>Now, in my Next.js code, I&#8217;ll simply replace the relative path of <code>/api/generateWorkout</code> with the full path <code>https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout</code>. After that, I&#8217;ll do the same for the other function&#8202;&#8212;&#8202;a very, very simple change.</p><pre><code>const fetchGpt4Data = async (userPrompt, exerciseList) =&gt; {
       const API_URL = "/api/generateWorkout";


       const requestOptions = {
           method: "POST",
           headers: {
               "Content-Type": "application/json",
           },
           body: JSON.stringify({
               userPrompt,
               exerciseList,
           }),
       };</code></pre><h3>Firebase Functions in Production</h3><p>Before testing the behavior of the functions within the Next.js web app, it&#8217;s probably wise to test this endpoint directly from the terminal first.</p><pre><code>curl -X POST -H "Content-Type: application/json" -d '{"userPrompt": "I want something basic that can help me get comfortable upside down with some wall assistance.", "exerciseList": "do your magic"}' https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout</code></pre><p>Unfortunately, I received this error:</p><p>B-Pro:~ alib$ curl -X POST -H &#8220;Content-Type: application/json&#8221; -d &#8216;{&#8220;userPrompt&#8221;: &#8220;I want something basic that can help me get comfortable upside down with some wall assistance.&#8221;, &#8220;exerciseList&#8221;: &#8220;do your magic&#8221;}&#8217; <a href="https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout">https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout</a></p><blockquote><p>&lt;title&gt;403 Forbidden&lt;/title&gt;</p><p>&lt;h2&gt;Your client does not have permission to get URL &lt;code&gt;/generateWorkout&lt;/code&gt; from this server.&lt;/h2&gt;</p></blockquote><p>I noticed (with help from <a href="https://stackoverflow.com/questions/47511677/firebase-cloud-function-your-client-does-not-have-permission-to-get-url-200-fr">Stack Overflow</a>) a &#8220;private&#8221; setting in the <code>package.json</code> in the <code>functions</code> folder, so I set it to <code>false</code> and redeployed. Didn&#8217;t work!</p><p>When I tested the function in the Firebase Cloud Function console, it worked as expected.</p><blockquote><p><a href="https://console.cloud.google.com/functions/details/us-central1/generateWorkout?env=gen1&amp;tab=testing&amp;authuser=0&amp;project=handstand-quest">https://console.cloud.google.com/functions/details/us-central1/generateWorkout?env=gen1&amp;tab=testing&amp;authuser=0&amp;project=handstand-quest</a></p></blockquote><p>I found steps from the same Stack Overflow thread that worked!</p><ul><li><p>Go to the Google Cloud Console (Not Firebase Console) -&gt; Search For Cloud Functions to see the list of functions</p></li><li><p>Click the checkbox next to the function you want to grant access to.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6h_v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6h_v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png 424w, https://substackcdn.com/image/fetch/$s_!6h_v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png 848w, https://substackcdn.com/image/fetch/$s_!6h_v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png 1272w, https://substackcdn.com/image/fetch/$s_!6h_v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6h_v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png" width="800" height="181" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:181,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6h_v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png 424w, https://substackcdn.com/image/fetch/$s_!6h_v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png 848w, https://substackcdn.com/image/fetch/$s_!6h_v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png 1272w, https://substackcdn.com/image/fetch/$s_!6h_v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7852af5e-4e05-475c-adc5-755c9b4b5680_800x181.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Select your Firebase functions from the Google Cloud Console</figcaption></figure></div><ul><li><p>Click Permissions at the top of the screen. The Permissions panel opens.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0urC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0urC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png 424w, https://substackcdn.com/image/fetch/$s_!0urC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png 848w, https://substackcdn.com/image/fetch/$s_!0urC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png 1272w, https://substackcdn.com/image/fetch/$s_!0urC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0urC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png" width="800" height="593" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:593,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0urC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png 424w, https://substackcdn.com/image/fetch/$s_!0urC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png 848w, https://substackcdn.com/image/fetch/$s_!0urC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png 1272w, https://substackcdn.com/image/fetch/$s_!0urC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4df82c6-39f3-4b16-a19b-0d4c5ba45d2d_800x593.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Manage permissions of Firebase functions</figcaption></figure></div><ul><li><p>Click &#8220;Add principal&#8221;</p></li><li><p>In the &#8220;New principals&#8221; field, type &#8220;allUsers&#8221;</p></li><li><p>Select the role &#8220;Cloud Functions&#8221; &gt; &#8220;Cloud Functions Invoker&#8221;</p></li><li><p>Select a role dropdown menu</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yH9T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yH9T!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png 424w, https://substackcdn.com/image/fetch/$s_!yH9T!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png 848w, https://substackcdn.com/image/fetch/$s_!yH9T!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png 1272w, https://substackcdn.com/image/fetch/$s_!yH9T!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yH9T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png" width="800" height="1003" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1003,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yH9T!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png 424w, https://substackcdn.com/image/fetch/$s_!yH9T!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png 848w, https://substackcdn.com/image/fetch/$s_!yH9T!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png 1272w, https://substackcdn.com/image/fetch/$s_!yH9T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf99af8d-d5ac-4a67-ac9b-46cc4ad0a874_800x1003.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cloud Functions Invoker to allUsers</figcaption></figure></div><ul><li><p>Click Save.</p></li></ul><p>Wisely, Google shows a message to prevent you from making this decision to make your cloud functions insecure.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qH4Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qH4Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png 424w, https://substackcdn.com/image/fetch/$s_!qH4Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png 848w, https://substackcdn.com/image/fetch/$s_!qH4Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png 1272w, https://substackcdn.com/image/fetch/$s_!qH4Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qH4Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png" width="800" height="370" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1bd188ce-a67b-4034-a567-e320ed784295_800x370.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:370,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qH4Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png 424w, https://substackcdn.com/image/fetch/$s_!qH4Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png 848w, https://substackcdn.com/image/fetch/$s_!qH4Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png 1272w, https://substackcdn.com/image/fetch/$s_!qH4Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bd188ce-a67b-4034-a567-e320ed784295_800x370.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Functions are now publicly accessible to everyone</figcaption></figure></div><p>Although insecure, I proceed with this option until I guard my web app with login/signup capabilities.</p><p>With this change, the curl request to the public endpoint works as expected. Now that I have the endpoint running, I will test call it from the app.</p><h3>Vercel Deployment</h3><p>Let&#8217;s test the change in the staging environment.</p><p>Since I initialized the Firebase <code>functions</code> folder in the Next.js project that gets deployed to Vercel; I need to tell Vercel to ignore this new folder. This is the error I currently get on deployment to Vercel.</p><blockquote><p>Type error: Cannot find module <code>firebase-functions</code> or its corresponding type declarations.</p></blockquote><p>To tell Vercel to ignore a folder, we can add a <code>.vercelignore</code> file to the root of our project and add the folder or files we want to ignore.</p><p>I added the following line to the <code>.vercelignore</code> file and pushed the change to the git branch, so Vercel could automatically handle the deployment to the staging environment.</p><pre><code>functions</code></pre><p><strong>Side note</strong>: If I deployed the Firebase functions to their own codebase, I wouldn&#8217;t have had to deal with this. Luckily, it&#8217;s a simple change to ignore the <code>functions</code> folder.</p><p>When testing in the staging environment, I got this error:</p><blockquote><p>Access to fetch at &#8216;https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout' from origin &#8216;https://hq-exercise-catalog-bl7zti3ol-alibad.vercel.app' has been blocked by CORS policy: No &#8216;Access-Control-Allow-Origin&#8217; header is present on the requested resource. If an opaque response serves your needs, set the request&#8217;s mode to &#8216;no-cors&#8217; to fetch the resource with CORS disabled.</p></blockquote><h3>Fixing CORS Issues</h3><p>I ran the Next.js local environment and went ahead and did some testing. I got the standard CORS error from localhost. It made me appreciate what Next.js/Vercel is doing behind the scenes.</p><blockquote><p>Access to fetch at &#8216;https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout' from origin &#8216;http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn&#8217;t pass access control check: No &#8216;Access-Control-Allow-Origin&#8217; header is present on the requested resource. If an opaque response serves your needs, set the request&#8217;s mode to &#8216;no-cors&#8217; to fetch the resource with CORS disabled.</p></blockquote><p><strong>Side note</strong>: This reminded me&#8230; It&#8217;s really expensive to build secure software, and by design, it slows companies down and has a major impact on reducing the innovation rate. Still, it&#8217;s necessary and the responsible thing to do. Building a side project, I don&#8217;t need to be that responsible!</p><p>The error message is a CORS (Cross-Origin Resource Sharing) issue. This issue happens when you try to make a request from a different origin (in this case </p><p>http://localhost:3000</p><p>) to a server (<code>https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout</code>) that doesn&#8217;t have the necessary headers to allow requests from different origins.</p><p>I added the CORS headers to the Cloud Functions to resolve this issue.</p><p>First, install the CORS npm package:</p><pre><code>npm install cors</code></pre><p>Wrap the login in each function with this:</p><pre><code>corsHandler(req, res, async () =&gt; {
    // current function code
}</code></pre><p>This will deploy the Cloud Functions with the updated CORS headers. With the above steps, the Cloud Functions should now allow requests from different origins.</p><p>Unfortunately, when I tried to call the Firebase Cloud Function from my Web App, I still got an error saying the CORS policy blocked that access. So, where is the CORS policy defined?</p><p>Let&#8217;s look at the requests and responses in the Network tab in the Google Chrome Developer Tools.</p><p>There is an initial preflight request, as shown below:</p><pre><code>OPTIONS https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout</code></pre><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8Q9r!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Q9r!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png 424w, https://substackcdn.com/image/fetch/$s_!8Q9r!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png 848w, https://substackcdn.com/image/fetch/$s_!8Q9r!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png 1272w, https://substackcdn.com/image/fetch/$s_!8Q9r!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Q9r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png" width="800" height="94" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7022e097-acbb-4395-830b-7ece83ed62be_800x94.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:94,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8Q9r!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png 424w, https://substackcdn.com/image/fetch/$s_!8Q9r!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png 848w, https://substackcdn.com/image/fetch/$s_!8Q9r!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png 1272w, https://substackcdn.com/image/fetch/$s_!8Q9r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7022e097-acbb-4395-830b-7ece83ed62be_800x94.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">OPTIONS 204</figcaption></figure></div><p>The OPTIONS request has an HTTP 204 from the server, with the following properties in the response header.</p><pre><code>access-control-allow-headers: content-type
access-control-allow-methods: GET,HEAD,PUT,PATCH,POST,DELETE
access-control-allow-origin: https://hq-exercise-catalog-bl7zti3ol-alibad.vercel.app</code></pre><p>The OPTIONS request is then followed by the POST Request.</p><pre><code>POST https://us-central1-handstand-quest.cloudfunctions.net/generateWorkout</code></pre><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GEar!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GEar!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png 424w, https://substackcdn.com/image/fetch/$s_!GEar!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png 848w, https://substackcdn.com/image/fetch/$s_!GEar!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png 1272w, https://substackcdn.com/image/fetch/$s_!GEar!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GEar!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png" width="800" height="125" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:125,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GEar!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png 424w, https://substackcdn.com/image/fetch/$s_!GEar!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png 848w, https://substackcdn.com/image/fetch/$s_!GEar!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png 1272w, https://substackcdn.com/image/fetch/$s_!GEar!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ae2b3d6-75e8-42f5-b521-7b6451761ef3_800x125.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">POST 408</figcaption></figure></div><p>The response for the POST request is an HTTP 408.</p><p>HTTP 408 status code, also known as &#8220;Request Timeout,&#8221; indicates the server did not receive a complete request from the client within the server&#8217;s allotted time limit.</p><p>This means Firebase is timing out too, and the resulting browser error is misleading!</p><p>The response also includes a Referrer Policy set to strict-origin-when-cross-origin.</p><h4>strict-origin-when-cross-origin</h4><p>Regarding the Referrer Policy set to strict-origin-when-cross-origin, this security feature controls how much referrer information should be included when a user navigates from one origin to another. It&#8217;s not directly related to the timeout issue or the CORS configuration, so I will ignore it.</p><h4>Firebase functions timeout limit</h4><p>So Firebase also happens to have that timeout. However, the difference is that Firebase lets you configure it without subscribing to a $20-per-month plan. By default, Firebase Cloud Functions have a timeout limit of 60 seconds. You can increase this limit to 540 seconds (nine minutes).</p><p>For the <code>generateExerciseData</code> function, the 60-second timeout is good enough since gpt-3.5-turbo is much faster than gpt-4, which is used in the <code>generateWorkout</code> function.</p><p>Increasing the timeout limit may result in higher resource usage and, thus, costs. However, I&#8217;m willing to try and see how that plays out. I highly doubt it&#8217;ll hit $20 every month. We&#8217;ll see how that goes with time when traffic patterns change. For now, I&#8217;m expecting it to cost less than $1 a month.</p><p>To change the amount of timeout in the <code>generateWorkout</code> Firebase function, let&#8217;s update the function definition in the <code>index.ts</code> file. I think I want it to wait up to three minutes.</p><pre><code>exports.generateWorkout = functions
  .runWith({ timeoutSeconds: 180 })
  .https.onRequest((req, res) =&gt; {
    // Your existing generateWorkout function code
  });</code></pre><p>I deployed the change to Firebase and finally got unblocked!</p><h3>Streaming (Timing in)</h3><p>To speed up the whole experience and make it easier to enjoy, streaming the GPT data and gradually reflecting that in the UI would be a good idea. This will reduce the time it takes to start seeing data, and it will avoid timeouts in the first place.</p><p>Upon reflection, it became clear that the current design approach was not optimal, which led to the need for a workaround to address the timeout issue. A more efficient approach would have been to deliver the data in smaller, more manageable chunks from the outset.</p><p>Time is a critical factor, and while transitioning from Next.js APIs to Firebase Functions, authentication and CORS issues caused a delay.</p><p>In my upcoming article, I will explore whether streaming is a more effective design strategy. It&#8217;ll all depend on how long it will take and whether unreasonable blockers come up.</p><p>It will be tricky, though, since my internal implementation gets GPT to return the exact JSON format, which would be hard to stream.</p><h3>Conclusion</h3><p>I hope this article gave you the idea and the details on how to update your Next.js application to use Firebase Cloud Functions instead of Vercel API endpoints.</p><p>By making this simple switch, you can save a significant amount in yearly costs without sacrificing the functionality of your application.</p><p>Although Vercel is an excellent platform, the ten-second timeout can be a hindrance. Nonetheless, I remain a big fan of Vercel and appreciate its numerous benefits.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Redefining Web Development: The Unbelievable Power of ChatGPT in a NextJS + React App]]></title><description><![CDATA[Moved from Medium. Original Post Date: April 10th 2023.]]></description><link>https://www.ali-b.com/p/redefining-web-development-the-unbelievable</link><guid isPermaLink="false">https://www.ali-b.com/p/redefining-web-development-the-unbelievable</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:51:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!u8x4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<pre><code>If anything, this post represents in detail the OpenAI GPT 4 capabilities as of April 2023, a good reminder how far we've come along.</code></pre><p>In this article, we&#8217;re diving headfirst into the remarkable potential of OpenAI&#8217;s ChatGPT and exploring how effortlessly it can be leveraged in a NextJS and React app. I am hoping you&#8217;ll find valuable insights into the development process, including the time required to code various components and the simplicity of incorporating ChatGPT into modern web applications.</p><p>Interestingly enough, I managed to squeeze in this project during my 10-day trip to Portugal, juggling multiple commitments, such as:</p><ol><li><p>Supporting my 12-year-old son as he joins Washington&#8217;s Soccer EPD team in the Iber Cup held in Portugal.</p></li><li><p>Tackling end-of-quarter work responsibilities, attending three meetings totaling four hours, and dedicating around six hours to focused work.</p></li><li><p>Spending quality time with my wife as we discover the enchanting city of Lisbon. Reuniting with my childhood friend, Abbass, after 12 long years. He traveled from Germany to spend two memorable days together with our families.</p></li></ol><p>Despite the packed schedule, I was determined to harness the power of ChatGPT and bring a new feature to life before returning to the daily grind in Seattle, WA. So, join me as I share my experience of balancing work, family, and cutting-edge web development on this unforgettable Portuguese adventure.</p><p><em><strong>Legend</strong></em></p><ul><li><p>&#128172; for working on this article and writing code with the help of ChatGPT.</p></li><li><p>&#9917; for soccer-related activities.</p></li><li><p>&#129782; for fun and quality time. You&#8217;ll notice I won&#8217;t be sharing out any details on this front, just to keep this article&#8217;s size manageable.</p></li><li><p>&#128084; updates related to spending time doing work for my employer.</p></li></ul><p><strong>Disclaimer</strong>: <em>While I don&#8217;t identify myself as a web developer per se, my background as a Software Engineering Manager and a generalist has equipped me with a passion for learning new technologies&#8202;&#8212;&#8202;especially when they can be used to achieve beneficial outcomes for others. So, regardless of your expertise level, I hope you&#8217;ll find valuable takeaways from my experience as I dabble in the world of web development with ChatGPT, NextJS, and React. Happy reading!</em></p><h3>Problem Statement</h3><p>Over the past few years, I have dedicated 2&#8211;12 hours per week to develop a mobile app, <a href="https://www.handstandquest.com">Handstand Quest</a>, aimed at helping individuals learn or improve their handstand skills. Four months ago, I decided to expand the project by creating a complementary web application using NextJS and React to enhance my React development expertise.</p><p>The existing web application, available at <a href="https://catalog.handstandquest.com">https://catalog.handstandquest.com</a>, displays a catalog of exercises, allowing users to access individual exercise pages for detailed instructions and YouTube videos.</p><p>To improve the user experience and encourage engagement, I seek to implement a straightforward and efficient mechanism at the bottom of the exercise list for users to suggest new exercises with minimal effort. This feature aims to keep the catalog fresh, comprehensive, and tailored to the diverse interests and preferences of the user base.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!u8x4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!u8x4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png 424w, https://substackcdn.com/image/fetch/$s_!u8x4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png 848w, https://substackcdn.com/image/fetch/$s_!u8x4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png 1272w, https://substackcdn.com/image/fetch/$s_!u8x4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!u8x4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png" width="800" height="457" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:457,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!u8x4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png 424w, https://substackcdn.com/image/fetch/$s_!u8x4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png 848w, https://substackcdn.com/image/fetch/$s_!u8x4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png 1272w, https://substackcdn.com/image/fetch/$s_!u8x4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc17337f5-95ce-4c70-85c4-6d34efc1456e_800x457.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Handstand Quest Exercise Catalog</figcaption></figure></div><p>As you reach the bottom of the exercise catalog, you&#8217;ll notice an empty space. In this area, I aim to introduce a user-friendly mechanism for suggesting new exercises.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kJnB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kJnB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png 424w, https://substackcdn.com/image/fetch/$s_!kJnB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png 848w, https://substackcdn.com/image/fetch/$s_!kJnB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png 1272w, https://substackcdn.com/image/fetch/$s_!kJnB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kJnB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png" width="800" height="317" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:317,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kJnB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png 424w, https://substackcdn.com/image/fetch/$s_!kJnB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png 848w, https://substackcdn.com/image/fetch/$s_!kJnB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png 1272w, https://substackcdn.com/image/fetch/$s_!kJnB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c9b50ef-0780-4b06-abdf-8ef5308ba416_800x317.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Place To Add &#8220;Suggest Exercise&#8221; Button</figcaption></figure></div><p>To provide some context on the type of data that would need to be provided to suggest an exercise, let&#8217;s take a look at the current design of an exercise page within the application.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3PtL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3PtL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png 424w, https://substackcdn.com/image/fetch/$s_!3PtL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png 848w, https://substackcdn.com/image/fetch/$s_!3PtL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png 1272w, https://substackcdn.com/image/fetch/$s_!3PtL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3PtL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png" width="800" height="491" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:491,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3PtL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png 424w, https://substackcdn.com/image/fetch/$s_!3PtL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png 848w, https://substackcdn.com/image/fetch/$s_!3PtL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png 1272w, https://substackcdn.com/image/fetch/$s_!3PtL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F902eef1b-dce9-4a18-b491-d3a55e7335a3_800x491.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Handstand Exercise Details Page</figcaption></figure></div><p>I would like to leverage GPT 4 to generate most of the code. I will not be listing all the code generated by ChatGPT. Instead, I will show the progression of the user interface and mention the specific prompts or tweaks to the code that I&#8217;ve had to make to get it to work the way I would expect.</p><div><hr></div><h3>Initial Prompt to ChatGPT</h3><p>I started right away, telling ChatGPT what I want.</p><blockquote><p>On my NextJS React TypeScript app, I would like to introduce a component that does the following:</p><p>- Asks the user, &#8220;Didn&#8217;t find an exercise you&#8217;re looking for?&#8221;. Place under that a button for the user to &#8220;Suggest an exercise&#8221;<br>- When the button is clicked, a very user friendly dialog opens up and it lets the user specify exercise information and submit or cancel. The dialog also has a close button in the top right corner.<br>- The exercise info consist of the following: Exercise name, Exercise category selected from a dropdown, Exercise subcategory, How To Instructions, One or more tips each having a title and a body, an image that could be uploaded or referenced via a link or looked up from a free online image library, a video that can be looked up from YouTube, and an intensity level that can range from 1 to 15.<br>- I would like to give the user an option, only after specifying a title, to fully generate the rest of the information by calling the GPTAPI.</p></blockquote><p>At a high level, without the code, here are the steps that ChatGPT asked me to follow:</p><ol><li><p>Install Material-UI and its dependencies, if you haven&#8217;t already.</p></li><li><p>Create a new file named ExerciseSuggestion.tsx and import the necessary dependencies.</p></li><li><p>Create the ExerciseSuggestion component with the following structure.</p></li><li><p>Add state variables and handlers for opening and closing the dialog, as well as handling form submission.</p></li><li><p>Implement the exercise input form inside the DialogContent component.</p></li><li><p>Add state variables and handlers for the form fields and GPT API call.</p></li><li><p>Implement the form field change handlers and bind them to the form fields.</p></li><li><p>Add the exercise category dropdown options and other form fields.</p></li><li><p>Create the handleTipsChange function for handling the addition and updates of tips.</p></li><li><p>Implement the tips input form and add the handleTipsChange function.</p></li><li><p>Implement the inputs for image and video.</p></li></ol><h3>Step 1: NPM Install</h3><p>On running the NPM install on the command line, I got this error.</p><blockquote><p>While resolving: undefined@undefined<br>Found: react@18.2.0<br>Could not resolve dependency: peer react@&#8221;&#185;&#8310;.8.0 || ^17.0.0" from @material-ui/core@4.12.4</p></blockquote><p>I prompted ChatGPT that I got this error on npm install. It gave me options to downgrade React or upgrade to the latest Material-UI version. I chose the latter. Note that it also suggested that if I choose the latter, I need to update my import statements.</p><p>Running the new NPM install succeeded.</p><h3>Steps 2, 3, 4 &amp; 5: ExerciseSuggestion Component</h3><p>To begin with, I asked it to rewrite this file based on the latest Material-UI version. I think it included steps 2&#8211;5 in the generated code.</p><p>It gave additional NPM components to install, which executed as expected on the command line. I then created a new file called <em>ExerciseSuggestion.tsx</em> and copied the code from ChatGPT.</p><p>It also included the following summary of what the file does:</p><blockquote><p>In this example, I&#8217;ve created a basic ExerciseSuggestion component that displays a button and a modal dialog when clicked. The dialog contains input fields for the exercise name, category, subcategory, and how-to instructions. You can extend this component by adding more input fields for tips, image, video, and intensity level as required.</p><p>Note that this example assumes you have an array of categories passed as a prop. You can replace this with your own data or fetch it from an API as needed.</p></blockquote><h3>New Step: Plugging the Component</h3><p>I told GPT to include the generated component in a parent component, that has categories in the following format:</p><pre><code>exerciseCategories: {
 id: ExerciseCategory
 categoryName: string
}[]</code></pre><p>I included the component as it suggested, while ignoring some of the other things it suggested like initializing the categories array.</p><pre><code>&lt;ExerciseSuggestion categories={exerciseCategories} /&gt;</code></pre><p>It then recommended that I update the ExerciseSuggestion component to accept the categories prop and map the categories correctly inside the Select component.</p><p>So I plugged in the code as it suggested. The only other thing I had to change was the type of the id, from string to my own defined ExerciseCategory enum.</p><pre><code>import { ExerciseCategory } from '../lib/exercises'


interface ExerciseSuggestionProps {
 categories: { id: ExerciseCategory; categoryName: string }[];
}</code></pre><p>This is how the app looks like now.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!h70I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!h70I!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png 424w, https://substackcdn.com/image/fetch/$s_!h70I!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png 848w, https://substackcdn.com/image/fetch/$s_!h70I!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png 1272w, https://substackcdn.com/image/fetch/$s_!h70I!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!h70I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png" width="800" height="234" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:234,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!h70I!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png 424w, https://substackcdn.com/image/fetch/$s_!h70I!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png 848w, https://substackcdn.com/image/fetch/$s_!h70I!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png 1272w, https://substackcdn.com/image/fetch/$s_!h70I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae0b19db-5138-428f-ba08-0da8755e20a3_800x234.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Newly Added &#8220;Suggest An Exercise&#8221; Button</figcaption></figure></div><p>When the &#8220;Suggest An Exercise&#8221; button is clicked, it opens this dialog.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tkjQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tkjQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png 424w, https://substackcdn.com/image/fetch/$s_!tkjQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png 848w, https://substackcdn.com/image/fetch/$s_!tkjQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png 1272w, https://substackcdn.com/image/fetch/$s_!tkjQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tkjQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png" width="800" height="380" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:380,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tkjQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png 424w, https://substackcdn.com/image/fetch/$s_!tkjQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png 848w, https://substackcdn.com/image/fetch/$s_!tkjQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png 1272w, https://substackcdn.com/image/fetch/$s_!tkjQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82dd05fd-d3ca-4b0f-b8fa-a97230152e4c_800x380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Dialog to Suggest an Exercise</figcaption></figure></div><p>At this point, I made my first git commit.</p><blockquote><p>Introduce a button to suggest an exercise and open a dialog to fill in basic details</p></blockquote><p><em><strong>March 30th </strong></em>&#128172;&#129782;: It took me about an hour to complete the coding and documentation up to this point. Earlier, I had spent over 3 hours working with GPT to finish the &#8220;Was This Helpful&#8221; feature visible in the Exercise Details Page screenshot I shared previously. After making good progress, I decided to take a break and pack my bags for my upcoming trip to Portugal before returning to the task later.</p><h3>Step 6: GPT API Call</h3><p>It&#8217;s now around half an hour past midnight. My brother-in-law and I are enjoying a well-deserved break, engaging in casual conversation and sharing a few laughs, all while watching some of his favorite shows. Amidst this relaxing atmosphere, I have my laptop in front of me, working on the project. Juggling a full-time job, I&#8217;ve learned to seize moments like these to &#8220;paint with code&#8221; and make progress on my passion projects.</p><p>I&#8217;ll skip this step for now until I have all the other parts completed.</p><h3>Step 7: Saving State in React</h3><p>In this step, I&#8217;ll integrate more code into the <em>ExerciseSuggestion</em> component, allowing the form updates to be saved as React properties. This way, they can be accessed later for tasks such as storing data in the backend or sending an email notification with the collected information.</p><p>After plugging in the code, I encountered an error. I shared the error with ChatGPT, and in response, I received an updated code solution to address the issue.</p><blockquote><p>I apologize for the confusion. It looks like the type of the event in the handleCategoryChange function is not compatible with the onChange event of the Material-UI Select component.</p></blockquote><p>I proceeded to update the handleCategoryChange function with the new code, and thankfully, no errors occurred. Below is a screenshot showcasing the recent modifications.</p><p>Interestingly, this time, ChatGPT included the code to display the &#8220;Intensity Level&#8221; field&#8202;&#8212;&#8202;a numeric value&#8202;&#8212;&#8202;along with the appropriate UI component to modify and maintain it as a number.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!o2YU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!o2YU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png 424w, https://substackcdn.com/image/fetch/$s_!o2YU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png 848w, https://substackcdn.com/image/fetch/$s_!o2YU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png 1272w, https://substackcdn.com/image/fetch/$s_!o2YU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!o2YU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png" width="800" height="601" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:601,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!o2YU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png 424w, https://substackcdn.com/image/fetch/$s_!o2YU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png 848w, https://substackcdn.com/image/fetch/$s_!o2YU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png 1272w, https://substackcdn.com/image/fetch/$s_!o2YU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc83b9004-180e-4d8b-adc5-eb113cd3e504_800x601.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Dialog Connected To React State Variables</figcaption></figure></div><h3>Step 8: Add Exercise Category Problem</h3><p>That has been already added in previously generated code, so skipping.</p><h3>Steps 9 &amp; 10: Add Tips</h3><p>I plugged in the code for tips, which added the JSX for this component, along with the JavaScript to store state and handle adding new tips.</p><p>Now, it shows an &#8220;Add Tip&#8221; button in the form.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dXCu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dXCu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png 424w, https://substackcdn.com/image/fetch/$s_!dXCu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png 848w, https://substackcdn.com/image/fetch/$s_!dXCu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png 1272w, https://substackcdn.com/image/fetch/$s_!dXCu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dXCu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png" width="800" height="569" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:569,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dXCu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png 424w, https://substackcdn.com/image/fetch/$s_!dXCu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png 848w, https://substackcdn.com/image/fetch/$s_!dXCu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png 1272w, https://substackcdn.com/image/fetch/$s_!dXCu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2c3ac22-dcc4-49b9-aa50-f2db399977f4_800x569.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Tips Entry Point</figcaption></figure></div><p>Upon clicking the &#8220;Add New Tip&#8221; button, the title and body fields for adding a tip are displayed, allowing you to add one or more tips. The positive aspect is that the tips fields were now automatically &#8220;connected&#8221; to React state variables.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jw4j!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jw4j!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png 424w, https://substackcdn.com/image/fetch/$s_!Jw4j!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png 848w, https://substackcdn.com/image/fetch/$s_!Jw4j!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png 1272w, https://substackcdn.com/image/fetch/$s_!Jw4j!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jw4j!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png" width="800" height="656" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d418448b-d683-4144-be7a-792791bb4835_800x656.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:656,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Jw4j!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png 424w, https://substackcdn.com/image/fetch/$s_!Jw4j!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png 848w, https://substackcdn.com/image/fetch/$s_!Jw4j!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png 1272w, https://substackcdn.com/image/fetch/$s_!Jw4j!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd418448b-d683-4144-be7a-792791bb4835_800x656.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Adding an Exercise Tip</figcaption></figure></div><p>Although the current user interface isn&#8217;t visually appealing, we plan to address that later.</p><h3>Step 11: Image and Video</h3><p>I revisited this step, and since the code appeared incomplete, I requested ChatGPT to provide the code for the image and video. However, I received the same response, so I decided to plug in the code anyway.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NGMv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NGMv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png 424w, https://substackcdn.com/image/fetch/$s_!NGMv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png 848w, https://substackcdn.com/image/fetch/$s_!NGMv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png 1272w, https://substackcdn.com/image/fetch/$s_!NGMv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NGMv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png" width="800" height="325" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:325,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NGMv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png 424w, https://substackcdn.com/image/fetch/$s_!NGMv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png 848w, https://substackcdn.com/image/fetch/$s_!NGMv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png 1272w, https://substackcdn.com/image/fetch/$s_!NGMv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1bb275b6-d4a2-4a13-92d1-0221abd630f3_800x325.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image and Video Url Fields</figcaption></figure></div><p>As a result, it merely added the text fields without URL validation. Ideally, I&#8217;d prefer a more user-friendly experience. I plan to address this issue later, but for now, I&#8217;ll git commit the progress made so far.</p><blockquote><p>Save React state and add new fields for tips, intensity level, video and image</p></blockquote><p>I pushed the git branch, and thanks to Vercel, I got a Slack notification that the deployment to the staging environment succeeded. I clicked on the &#8220;Visit&#8221; button in Slack to manually confirm all the new changes in the staging environment.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ok6R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ok6R!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png 424w, https://substackcdn.com/image/fetch/$s_!ok6R!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png 848w, https://substackcdn.com/image/fetch/$s_!ok6R!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png 1272w, https://substackcdn.com/image/fetch/$s_!ok6R!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ok6R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png" width="800" height="212" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:212,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ok6R!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png 424w, https://substackcdn.com/image/fetch/$s_!ok6R!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png 848w, https://substackcdn.com/image/fetch/$s_!ok6R!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png 1272w, https://substackcdn.com/image/fetch/$s_!ok6R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6522a699-3d8a-4304-a645-9af1a72ee91c_800x212.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Verifying in Staging Environment</figcaption></figure></div><div><hr></div><h3>Refining The User Experience</h3><p>Having completed the initial steps recommended by ChatGPT, it&#8217;s time for me to take a step back and evaluate the current user experience to determine my next course of action.</p><p>To stay focused on what&#8217;s essential, I revisit my original requirements. I&#8217;ve resolved to prioritize a solid user experience before diving into leveraging GPT for generating exercise content. While the excitement may have diminished slightly, I remain committed to achieving the desired outcome, as witnessing the final result will be rewarding in itself!</p><h4>Category Field Title</h4><p>I&#8217;ll start with the little things. Looking at the UI, when the user tries to pick a category, the field title shows with the field border striking through it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!crDR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!crDR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png 424w, https://substackcdn.com/image/fetch/$s_!crDR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png 848w, https://substackcdn.com/image/fetch/$s_!crDR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png 1272w, https://substackcdn.com/image/fetch/$s_!crDR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!crDR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png" width="800" height="637" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:637,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!crDR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png 424w, https://substackcdn.com/image/fetch/$s_!crDR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png 848w, https://substackcdn.com/image/fetch/$s_!crDR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png 1272w, https://substackcdn.com/image/fetch/$s_!crDR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd346aa9c-ce51-45c2-87f5-1d5a8964df9f_800x637.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Border Strike-Through Exercise Category Field Title</figcaption></figure></div><p>I also see the same behavior in the tip body and title.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gPf0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gPf0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png 424w, https://substackcdn.com/image/fetch/$s_!gPf0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png 848w, https://substackcdn.com/image/fetch/$s_!gPf0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png 1272w, https://substackcdn.com/image/fetch/$s_!gPf0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gPf0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png" width="800" height="234" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2d2c06da-259e-4257-ba92-246da20de484_800x234.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:234,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gPf0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png 424w, https://substackcdn.com/image/fetch/$s_!gPf0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png 848w, https://substackcdn.com/image/fetch/$s_!gPf0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png 1272w, https://substackcdn.com/image/fetch/$s_!gPf0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2c06da-259e-4257-ba92-246da20de484_800x234.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Tip Border Strike-Through Fields&#8217; Titles</figcaption></figure></div><p>So I ask ChatGPT.</p><blockquote><p>When the exercise category field is in focus mode, the border of the field is striking through the title.</p></blockquote><p>ChatGPT gave me back the code to add a background color to the label (field title) and some padding, so it does not overlap with the border when the input is focused. Although it&#8217;s not what I was thinking exactly, I decided to give it a try and see what it looks like.</p><p>The code gave some errors, related to deprecated code and a div referencing a CSS file. It dawned on me that I haven&#8217;t needed a single css change so far!</p><p><em><strong>March 31st </strong></em>&#129782;: <em>Anyways, I&#8217;m tired right now, and I am going to bed. I&#8217;ll come back to this as soon as life lets me.</em></p><p><em><strong>March 31st </strong></em>&#128172;: <em>Next morning, I have 30 minutes before Uber shows up for the ride to the airport. Let&#8217;s see if I can get this done.</em></p><p>One minute later with minor tweaks, I got the code running and I am actually happy with the results.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vK3n!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vK3n!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png 424w, https://substackcdn.com/image/fetch/$s_!vK3n!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png 848w, https://substackcdn.com/image/fetch/$s_!vK3n!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png 1272w, https://substackcdn.com/image/fetch/$s_!vK3n!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vK3n!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png" width="800" height="487" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:487,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vK3n!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png 424w, https://substackcdn.com/image/fetch/$s_!vK3n!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png 848w, https://substackcdn.com/image/fetch/$s_!vK3n!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png 1272w, https://substackcdn.com/image/fetch/$s_!vK3n!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fc2c88-08ca-406f-92ba-35a0e4d9952c_800x487.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Exercise Category Dropdown</figcaption></figure></div><h4>Tips Title and Body Fields</h4><p>I need to do the same for the tip body and description. So I asked ChatGPT, and it gave me the code and told me that the code will apply the required styles to the title and body fields of tips, ensuring that the border does not strike through the label.</p><p>There was an error because it decided to introduce a change handler for each of the tip title and body, when in the past it had one change handler for both. I fed it the error and it gave me the two new functions to plug in. there was another error, which I fed back in and now it gave me the correct code.</p><p>Ok, so the field now renders nicely when it is focused.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IKLp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IKLp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png 424w, https://substackcdn.com/image/fetch/$s_!IKLp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png 848w, https://substackcdn.com/image/fetch/$s_!IKLp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png 1272w, https://substackcdn.com/image/fetch/$s_!IKLp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IKLp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png" width="800" height="124" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:124,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IKLp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png 424w, https://substackcdn.com/image/fetch/$s_!IKLp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png 848w, https://substackcdn.com/image/fetch/$s_!IKLp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png 1272w, https://substackcdn.com/image/fetch/$s_!IKLp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32a2c1ef-dec6-4467-84e1-c155acfaa14e_800x124.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Tip Title Field</figcaption></figure></div><p>However, it&#8217;s broken when the text fields have text in it.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bfkv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bfkv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png 424w, https://substackcdn.com/image/fetch/$s_!Bfkv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png 848w, https://substackcdn.com/image/fetch/$s_!Bfkv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png 1272w, https://substackcdn.com/image/fetch/$s_!Bfkv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bfkv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png" width="800" height="227" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:227,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Bfkv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png 424w, https://substackcdn.com/image/fetch/$s_!Bfkv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png 848w, https://substackcdn.com/image/fetch/$s_!Bfkv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png 1272w, https://substackcdn.com/image/fetch/$s_!Bfkv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F612bcef5-84de-44a9-98cd-b9e1c9eb405e_800x227.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Broken Tips Fields Experience</figcaption></figure></div><p>Well, in this case, I feel like ChatGPT complicated my life a bit and made me a bit dumber. What I need to do is figure out whether I should continue down the path.</p><p>I&#8217;m choosing to just remove all the new code and get back to the original state, then just tell ChatGPT to add some vertical padding to the tip title and body.</p><p>Now, I am paying a bit more attention (learning mode) and I asked ChatGPT what the syntax is all about.</p><blockquote><p>The sx prop is a shorthand property provided by Material-UI to apply styles to a component. It allows you to define style rules using an object syntax, where keys correspond to CSS properties, and values represent the styles to apply.</p><p>In this case, sx={{ mt: 2, mb: 1 }} is setting the top margin (mt) to 2 units and the bottom margin (mb) to 1 unit. Material-UI uses an 8px spacing unit by default, so 2 units will correspond to 16px (2 * 8px) and 1 unit will correspond to 8px (1 * 8px).</p><p>The sx prop can be used to apply various styles, such as padding, margin, color, and more, in a concise and convenient way.</p></blockquote><p>So all I did was just add the sx property to each of the two fields (title and body). Now, I have a fix to the strikethrough issue!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DjQw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DjQw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png 424w, https://substackcdn.com/image/fetch/$s_!DjQw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png 848w, https://substackcdn.com/image/fetch/$s_!DjQw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png 1272w, https://substackcdn.com/image/fetch/$s_!DjQw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DjQw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png" width="800" height="478" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:478,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DjQw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png 424w, https://substackcdn.com/image/fetch/$s_!DjQw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png 848w, https://substackcdn.com/image/fetch/$s_!DjQw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png 1272w, https://substackcdn.com/image/fetch/$s_!DjQw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F327f94eb-7072-4867-89c6-9699775cd6c8_800x478.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Tips Strike-Through Issue Fixed!</figcaption></figure></div><p>Time for a git commit:</p><blockquote><p>Fix issue where border of field strikes through its title for categories and tips title/body</p></blockquote><p><em><strong>March 31st </strong></em>&#129782;: <em>10 minutes before Uber is here. Time to get in travel mode.</em></p><h4>Tips Grouping</h4><p><em><strong>March 31st </strong></em>&#128172; &#9917;: <em>Alright, I am back. It&#8217;s 1 pm and I&#8217;m at the airport. My flight departs at 6 pm. I&#8217;m that early as I had to drop my kid for an earlier flight with his soccer team. Actually, that&#8217;s the main reason I am traveling to Portugal. Washington <a href="https://washingtonyouthsoccer.org/elite-player-development/">EPD team</a> is practicing with Academia Cristiano Ronaldo&#8202;&#8212;&#8202;Sporting Clube de Portugal, then participating in the <a href="https://www.ibercup.com/">Iber Cup</a>, which is one of the largest Youth Football/ Soccer Tournaments on the planet.</em></p><p>The next quick win in the user experience I want to have is to be able to easily differentiate the list of tips. Right now, it&#8217;s confusing.</p><blockquote><p>I want to place the title and body into a Tip box that represents the order of the tip in the tips array. For example, the first tip would have a box with title &#8220;Tip 1&#8221; and within it, there would be a &#8220;Title&#8221; field and a &#8220;body&#8221; field.</p></blockquote><p>I just pasted the paragraph above into ChatGPT and incorporated the provided code, which involved importing a new component from React. Although the code triggered an error, fixing it was a straightforward task.</p><p>The updated user interface, as shown below, may not be perfect, but it&#8217;s a considerable improvement compared to its previous state. For the time being, I am satisfied with the progress.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5MX5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5MX5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png 424w, https://substackcdn.com/image/fetch/$s_!5MX5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png 848w, https://substackcdn.com/image/fetch/$s_!5MX5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png 1272w, https://substackcdn.com/image/fetch/$s_!5MX5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5MX5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png" width="800" height="800" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:800,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5MX5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png 424w, https://substackcdn.com/image/fetch/$s_!5MX5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png 848w, https://substackcdn.com/image/fetch/$s_!5MX5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png 1272w, https://substackcdn.com/image/fetch/$s_!5MX5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb88e9da4-d91e-4b57-a39b-9582c5d66d4c_800x800.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Boxed Tips</figcaption></figure></div><p>I have a bug though. Whenever I type something in the body, it shows it in the title and limits it to one character. Weird.</p><p>I pass the exact paragraph as is to ChatGPT and I plug in the changes, problem solved! For some reason, I don&#8217;t know why, and for now, I don&#8217;t care. I want to move on to building something fun.</p><p>Wait, it was actually my error copy/pasting the same handler code parameters for both the title and the body, so it was updating the title when I was updating the body!</p><p>One last thing, I noticed there is no mechanism to remove a tip once it is added, so I&#8217;ve asked ChatGPT to add a close button in the top right corner of the tip box that would remove the tip box and the tip item from the array.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tXR4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tXR4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png 424w, https://substackcdn.com/image/fetch/$s_!tXR4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png 848w, https://substackcdn.com/image/fetch/$s_!tXR4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png 1272w, https://substackcdn.com/image/fetch/$s_!tXR4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tXR4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png" width="800" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d72faf99-d0f8-4122-982d-64b7438c605b_800x374.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tXR4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png 424w, https://substackcdn.com/image/fetch/$s_!tXR4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png 848w, https://substackcdn.com/image/fetch/$s_!tXR4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png 1272w, https://substackcdn.com/image/fetch/$s_!tXR4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd72faf99-d0f8-4122-982d-64b7438c605b_800x374.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">X on the Tip Title Field</figcaption></figure></div><p>I plugged the code in and it added the X on the Title field. I kind of want it on the box itself above the title field. Once more, I&#8217;ve resolved that issue by talking with ChatGPT.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!m_Lf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!m_Lf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png 424w, https://substackcdn.com/image/fetch/$s_!m_Lf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png 848w, https://substackcdn.com/image/fetch/$s_!m_Lf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png 1272w, https://substackcdn.com/image/fetch/$s_!m_Lf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!m_Lf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png" width="800" height="466" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/163085f4-19d1-472c-9099-24f429d55de4_800x466.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:466,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!m_Lf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png 424w, https://substackcdn.com/image/fetch/$s_!m_Lf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png 848w, https://substackcdn.com/image/fetch/$s_!m_Lf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png 1272w, https://substackcdn.com/image/fetch/$s_!m_Lf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F163085f4-19d1-472c-9099-24f429d55de4_800x466.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">X on the Tip Box</figcaption></figure></div><div><hr></div><h3>Exercise Image Experience</h3><p>I&#8217;m trying to remember the name of some websites that offer free images, so I just asked ChatGPT.</p><blockquote><p>- Unsplash (</p><p>https://unsplash.com/</p><p>): Offers high-resolution photos contributed by photographers from around the world. You can use these images for free with proper attribution.<br>- Pexels (</p><p>https://www.pexels.com/</p><p>): Offers a wide variety of free stock photos and videos, which can be used for personal and commercial projects without attribution.<br>- Pixabay (</p><p>https://pixabay.com/</p><p>): Provides a large collection of free images, illustrations, vector graphics, and videos under a Creative Commons Zero (CC0) license, which allows for use without attribution.<br>- Burst (</p><p>https://burst.shopify.com/</p><p>): Powered by Shopify, Burst offers free high-resolution images for entrepreneurs. These images can be used for personal and commercial projects.<br>- Freepik (</p><p>https://www.freepik.com/</p><p>): Offers free and premium vector graphics, illustrations, and photos. You can use free resources with proper attribution.</p></blockquote><p>Given the above description, although I am very familiar with Unsplash, I had no idea it required attribution! For this reason, I decided to explore Pexels and Pixabay. Hopefully, they are at the same level of quality as Unspalsh.</p><p><em><strong>March 31st </strong></em>&#129782;: <em>That said, I need to go give my wife a 5 minute massage, because we had a deal, to take turns massaging each other. Be right back.</em></p><p><em><strong>March 31st </strong></em>&#128172;: <em>Ok, I am back at 1:40 pm.</em></p><p>I&#8217;ll just go ahead and explore whether there is an easy way to let a user lookup an image from Pexels. Here is my prompt to GPT:</p><blockquote><p>Enable the user to lookup images from Pexels and when the user selects an image, update the value of the Image TextField to the url of the selected image.</p></blockquote><p>Here are the things GPT told me to do. Let&#8217;s see how long this will take.</p><blockquote><p>- Get a Pexels API key by signing up for a free account at<a href="https://www.pexels.com/api/new/"> https://www.pexels.com/api/new/</a>. Make sure to replace &#8220;YOUR_PEXELS_API_KEY&#8221; with your actual Pexels API key.<br>- Install Axios, a popular HTTP client for making API requests, if you haven&#8217;t already:<br>- Create a new state variable to store the search results and the selected image URL:<br>- Create a function to search for images using the Pexels API:<br>- Create a function to handle selecting an image from the search results:<br>- Create a UI to search for images and display the results. You can use Material-UI components like TextField, Button, and Grid for this. When a user clicks on an image, call the handleImageSelect function with the image URL.</p></blockquote><p>In about a minute, I generated a Pexels API key. I then npm installed Axios with no issues. I easily plugged in steps 3 and 4 into the code. Steps 4 and 5 didn&#8217;t look like they would plugin well into my component, so I explicitly asked ChatGPT again to give me the code as part of the <em>ExerciseSuggestion</em> component.</p><blockquote><p>Can you give me this code as part of the ExerciseSuggestion component</p></blockquote><p>It generated the code for the component, but not all of it, so I had to carefully pick what I wanted to plug in.</p><ul><li><p>It seemed like it updated the dialog to have the top right close button that I initially requested, so I thought I might as well copy that part and see what it looks like. This produced some errors due to referencing new components from new libraries, so I just imported those.</p></li><li><p>I copied the logic to search images. I made some minor variable and method name changes, along with including new components.</p></li></ul><p>And there you have it&#8202;&#8212;&#8202;this is what the current UI looks like. Although it functions well, there&#8217;s still room for improvement in the overall user experience.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_QLV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_QLV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png 424w, https://substackcdn.com/image/fetch/$s_!_QLV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png 848w, https://substackcdn.com/image/fetch/$s_!_QLV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png 1272w, https://substackcdn.com/image/fetch/$s_!_QLV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_QLV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png" width="800" height="1118" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1118,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_QLV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png 424w, https://substackcdn.com/image/fetch/$s_!_QLV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png 848w, https://substackcdn.com/image/fetch/$s_!_QLV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png 1272w, https://substackcdn.com/image/fetch/$s_!_QLV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd13d4d0-7648-44d0-8313-9b11f909344c_800x1118.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image Search from Pexels</figcaption></figure></div><p><em><strong>March 31st </strong></em>&#128172; &#129782;<em>: It&#8217;s currently 2 o&#8217;clock, so it took me around 20 minutes to complete. However, I had some distractions while talking to my wife, so I believe the outcome is still solid. I&#8217;m git-committing this change then going for a break.</em></p><blockquote><p>Enable user to search images from Pexel</p></blockquote><h4>Improve Exercise Image Experience</h4><p><em><strong>March 31st </strong></em>&#128172; &#129782;<em>: I am back from the break, 4 hours later. I tried to sleep but couldn&#8217;t. My flight got delayed by an hour. I don&#8217;t care, I am coding with ChatGPT.</em></p><p>Observing the current experience, there a few things I&#8217;d like to explore:</p><ol><li><p>It&#8217;s confusing to the user that if you search images, they will show up. It&#8217;s also not clear that when you click on an image, it will automatically populate the Url field. Also it&#8217;s confusing having both the Url and Search fields showing at the same time without additional cues.</p></li><li><p>Given that I won&#8217;t actually end up using the exact images for the exercise, copyrighting is not much of a big deal. So I&#8217;m thinking I want to fetch the images via a Google search instead for accuracy.</p></li><li><p>For the API tokens in the code, I want to make sure those are securely stored in environment variables rather than in the code.</p></li></ol><p>I just dumped the first two bullets above unto ChatGPT to see what I would get.</p><p>I got some new code, and it replaced the image search capability with an <em>ImageSearch</em> component. So I asked it to generate the code for that component and plugged everything in. Things are a little better, but not yet what I was looking for.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6ANZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6ANZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png 424w, https://substackcdn.com/image/fetch/$s_!6ANZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png 848w, https://substackcdn.com/image/fetch/$s_!6ANZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png 1272w, https://substackcdn.com/image/fetch/$s_!6ANZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6ANZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png" width="800" height="577" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:577,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6ANZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png 424w, https://substackcdn.com/image/fetch/$s_!6ANZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png 848w, https://substackcdn.com/image/fetch/$s_!6ANZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png 1272w, https://substackcdn.com/image/fetch/$s_!6ANZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1c6004d-1271-44e6-add0-beb29a0beb08_800x577.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Separating &#8220;Search Images&#8221; and &#8220;Image Url&#8221; fields via Toggle Buttons</figcaption></figure></div><p>I asked ChatGPT to replace the ToggleButton with a Chip, and now it looks as follows:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6ZLv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6ZLv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png 424w, https://substackcdn.com/image/fetch/$s_!6ZLv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png 848w, https://substackcdn.com/image/fetch/$s_!6ZLv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png 1272w, https://substackcdn.com/image/fetch/$s_!6ZLv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6ZLv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png" width="800" height="153" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:153,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6ZLv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png 424w, https://substackcdn.com/image/fetch/$s_!6ZLv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png 848w, https://substackcdn.com/image/fetch/$s_!6ZLv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png 1272w, https://substackcdn.com/image/fetch/$s_!6ZLv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc341e3e2-6b08-46ca-92f2-e7cef2d99fce_800x153.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Chips looks nicer than Toggle Buttons</figcaption></figure></div><h3>Fields Grouping in Tabs</h3><p>The &#8220;Suggest Exercise&#8221; form has way too many fields at this point. ChatGPT generated the skeleton code for me based on this request. I took the skeleton code and plugged it into the file accordingly.</p><blockquote><p>Here is the latest code for ExerciseSuggestion.</p><p>&lt;all the code&gt;</p><p>I want to add tabs at the top that would include different set of fields as follows:</p><p>- About, which includes Exercise name, category, subcategory and How to Instructions.<br>- Media, which includes the image url/search and the video url<br>- Tips, which includes the tips, defaulting to one entry in the tips array on initialization</p></blockquote><p>I now have all the fields grouped. First tab looks good.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lflm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lflm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png 424w, https://substackcdn.com/image/fetch/$s_!lflm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png 848w, https://substackcdn.com/image/fetch/$s_!lflm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png 1272w, https://substackcdn.com/image/fetch/$s_!lflm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lflm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png" width="800" height="852" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:852,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lflm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png 424w, https://substackcdn.com/image/fetch/$s_!lflm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png 848w, https://substackcdn.com/image/fetch/$s_!lflm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png 1272w, https://substackcdn.com/image/fetch/$s_!lflm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6cf17bd8-eac3-424e-a3f8-5c0a9df7d07e_800x852.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Organizing Fields in Tabs</figcaption></figure></div><p>Second tab for the Media, not as much. Also, image search regressed. Not sure if that happened now or earlier with component refactoring. I&#8217;ll get to it later.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0l6q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0l6q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png 424w, https://substackcdn.com/image/fetch/$s_!0l6q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png 848w, https://substackcdn.com/image/fetch/$s_!0l6q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png 1272w, https://substackcdn.com/image/fetch/$s_!0l6q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0l6q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png" width="788" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:788,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0l6q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png 424w, https://substackcdn.com/image/fetch/$s_!0l6q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png 848w, https://substackcdn.com/image/fetch/$s_!0l6q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png 1272w, https://substackcdn.com/image/fetch/$s_!0l6q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2f9a14d-ae70-4b22-8345-6fef0faad9c3_788x720.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Media Tab doesn&#8217;t look great now</figcaption></figure></div><p>The tips dialog should have at least one item already pre-created by default.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ze3u!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ze3u!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png 424w, https://substackcdn.com/image/fetch/$s_!Ze3u!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png 848w, https://substackcdn.com/image/fetch/$s_!Ze3u!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png 1272w, https://substackcdn.com/image/fetch/$s_!Ze3u!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ze3u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png" width="616" height="442" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/08526874-e8c0-4249-8989-00548e99641e_616x442.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:442,&quot;width&quot;:616,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ze3u!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png 424w, https://substackcdn.com/image/fetch/$s_!Ze3u!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png 848w, https://substackcdn.com/image/fetch/$s_!Ze3u!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png 1272w, https://substackcdn.com/image/fetch/$s_!Ze3u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08526874-e8c0-4249-8989-00548e99641e_616x442.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Tips tab</figcaption></figure></div><p>I also want both the Media and the Tips tabs to retain the same width as the About tab.</p><h4>Coding Without ChatGPT</h4><p><em><strong>March 31st </strong></em>&#128172; &#129782;<em>: I am now on the airplane, with no internet connection. To be honest, I feel some inner friction continuing, just given how much faster I could be going if I was working with ChatGPT.</em></p><p>I&#8217;ll push through just to fix those last issues I&#8217;ve discovered in the following order.</p><ol><li><p>Fix the layout in the Media tab</p></li><li><p>Fix the issue with image search not working. I think this is due to the lack of internet connection, so skipping for now.</p></li><li><p>Have a default tip created</p></li><li><p>Fix the width of the dialog no matter which tab is selected</p></li></ol><p>Those were such quick fixes, and I don&#8217;t think it would have been that much faster doing it via ChatGPT.</p><h4>Intensity Level</h4><p>I&#8217;d prefer a more consistent and user friendly experience for the intensity level. Currently, it&#8217;s a number field that can be changed with a spinner.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5mdI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5mdI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png 424w, https://substackcdn.com/image/fetch/$s_!5mdI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png 848w, https://substackcdn.com/image/fetch/$s_!5mdI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png 1272w, https://substackcdn.com/image/fetch/$s_!5mdI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5mdI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png" width="800" height="108" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:108,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5mdI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png 424w, https://substackcdn.com/image/fetch/$s_!5mdI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png 848w, https://substackcdn.com/image/fetch/$s_!5mdI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png 1272w, https://substackcdn.com/image/fetch/$s_!5mdI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb807d9-035b-44c4-8904-8877e7fa9d19_800x108.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Intensity Level as a Spinner Text Field</figcaption></figure></div><p>I&#8217;d like to use instead the existing &#8220;Intensity Level&#8221; component that shows up when you open an exercise details.</p><p>To do that, I replaced the &lt;TextField&gt; with &lt;IntensityLevel&gt; and plugged in the IntensityLevel an onChange event handler that lets it notify the parent component of the changed intensity level.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xxmr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xxmr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png 424w, https://substackcdn.com/image/fetch/$s_!xxmr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png 848w, https://substackcdn.com/image/fetch/$s_!xxmr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png 1272w, https://substackcdn.com/image/fetch/$s_!xxmr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xxmr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png" width="800" height="822" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e7c73e0f-53b7-4805-8282-018461aac341_800x822.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:822,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xxmr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png 424w, https://substackcdn.com/image/fetch/$s_!xxmr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png 848w, https://substackcdn.com/image/fetch/$s_!xxmr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png 1272w, https://substackcdn.com/image/fetch/$s_!xxmr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7c73e0f-53b7-4805-8282-018461aac341_800x822.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Using the existing IntensityLevel Component</figcaption></figure></div><p><em><strong>March 31st</strong></em> &#129782;<em>: I managed to get the above done before I was asked to stow away my laptop for takeoff. However, for the rest of the flight, I tried to get some sleep but unfortunately, I was unsuccessful.</em></p><div><hr></div><h3>Image Experience&#8202;&#8212;&#8202;Continued</h3><p><em><strong>April 2nd </strong></em>&#128172; &#129782;<em><strong>: </strong>Alright, I am in Lisbon, Portugal right now, sitting on the balcony. Last night and this morning, we went out and explored the neighborhood. I will work for about an hour then go to a local market.</em></p><p>Looking at the current experience:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XWgV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XWgV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png 424w, https://substackcdn.com/image/fetch/$s_!XWgV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png 848w, https://substackcdn.com/image/fetch/$s_!XWgV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png 1272w, https://substackcdn.com/image/fetch/$s_!XWgV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XWgV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png" width="800" height="363" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:363,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XWgV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png 424w, https://substackcdn.com/image/fetch/$s_!XWgV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png 848w, https://substackcdn.com/image/fetch/$s_!XWgV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png 1272w, https://substackcdn.com/image/fetch/$s_!XWgV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78cbf847-5385-4ace-897b-1f375d1dabee_800x363.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Media Tab</figcaption></figure></div><blockquote><p>For the image url and search experience in the Media tab, I would like to make the following changes:</p><p>- Combine the &#8220;Image Url&#8221; text field and the &#8220;Search Images&#8221; text field into one Text Field with placeholder text &#8220;Search Google or type/paste an Image URL&#8221;.<br>- Show a search icon in the &#8220;Search Images&#8221; field<br>- Include a button on the right side of the text field that lets a user upload an image. When the image is selected, it is uploaded to Firebase storage, with a field name that matches the exercise name, with spaces replaced by underscore characters. The text field is updated with the new image url, and the image is previewed in the space below the text field.<br>- When there is text in the field, show a &#8220;clear&#8221; button. Add a separator between the clear button and the image upload button to its right.<br>- When the user enters a valid url, validate that the url points to an image. If it does, preview the image in the space below the text field. If it is a url that does not point to an image, show an error message. Otherwise, if it is not a Url, search Google (instead of Pexel) based on the text in the text field. The user should see a gallery of images corresponding to the search result. The user should be able to navigate the image pages. When the user selects an image, hide the image gallery, update the text field with the Url, and preview the image in the space below the text field.</p></blockquote><p>I told ChatGPT to give me the code for the above given the current code I have for the <em>ImageSearch.tsx</em> component.</p><p>It generated the code with the following instructions:</p><blockquote><p>This updated version of ImageSearch.tsx includes the combined TextField with the search icon, clear button, and image upload button. It also adds the image preview below the TextField for the selected image. Finally, it retains the original functionality of displaying search results in a Grid.</p><p>Make sure to replace the `searchImages` function with a call to the Google Custom Search API instead of the Pexels API. Also, replace `&#8217;Your_Exercise_Name&#8217;` with the actual exercise name in the `handleImageUpload` function.</p></blockquote><p>After plugging in the code and fixing how Firebase storage is being imported and used, here is the updated UI I see.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dKtd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dKtd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png 424w, https://substackcdn.com/image/fetch/$s_!dKtd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png 848w, https://substackcdn.com/image/fetch/$s_!dKtd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png 1272w, https://substackcdn.com/image/fetch/$s_!dKtd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dKtd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png" width="800" height="1109" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1109,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dKtd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png 424w, https://substackcdn.com/image/fetch/$s_!dKtd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png 848w, https://substackcdn.com/image/fetch/$s_!dKtd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png 1272w, https://substackcdn.com/image/fetch/$s_!dKtd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25ecaba8-973b-4909-a695-c7c29db2aa96_800x1109.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image Selection</figcaption></figure></div><p>Few things work:</p><ul><li><p>Search icon and clear button added.</p></li><li><p>A preview image is added when you select and image from the gallery</p></li><li><p>When the clear button is clicked, it clears the text, the preview image and the gallery</p></li><li><p>File upload button is added and lets you selected a file to upload</p></li></ul><p>Few things did not change or do not work as expected:</p><ul><li><p>After uploading a file, nothing happens. This is likely an error I need to resolve.</p></li><li><p>Image search is still going through Pexels.</p></li><li><p>No page navigation added in image search gallery</p></li><li><p>The Image URL field is still there along with the URL/Search Chips</p></li></ul><p>Part of this is not ChatGPT&#8217;s fault, since I only gave it the code of the <em>ImageSearch</em> component, while the Image URL and Chips actually live in the parent Component.</p><h4>Merging Search Keyword and Url for Image</h4><p>I provided the code for parent component and asked ChatGPT:</p><blockquote><p>I want to remove the URL and Search Chips, and merge the Image URL field with the ImageSearch component as described earlier.</p></blockquote><p>Selecting an image now updates the Image URL field.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YlyJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YlyJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png 424w, https://substackcdn.com/image/fetch/$s_!YlyJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png 848w, https://substackcdn.com/image/fetch/$s_!YlyJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png 1272w, https://substackcdn.com/image/fetch/$s_!YlyJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YlyJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png" width="800" height="533" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:533,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YlyJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png 424w, https://substackcdn.com/image/fetch/$s_!YlyJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png 848w, https://substackcdn.com/image/fetch/$s_!YlyJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png 1272w, https://substackcdn.com/image/fetch/$s_!YlyJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c75e3ab-3a6b-4d83-834f-fb2a460d6c1f_800x533.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>My intention was to combine the Image URL field and the Search field into one. I&#8217;ll reiterate that to ChatGPT.</p><blockquote><p>Combine the Image URL and Search fields into one. Name the new field &#8220;Image URL&#8221; and move the current field title as placeholder text &#8220;Search Google or type an Image URL&#8221;.</p></blockquote><p>Also, apply the following requirements I mentioned earlier:</p><ul><li><p>When the user enters a valid url, validate that the url points to an image. If it does, preview the image in the space below the text field.</p></li><li><p>If it is a url that does not point to an image, show an error message. Otherwise, if it is not a Url, search Google (instead of Pexel) based on the text in the text field. The user should see a gallery of images corresponding to the search result.</p></li><li><p>The user should be able to navigate the image pages.</p></li><li><p>When the user selects an image, hide the image gallery, update the text field with the Url, and preview the image in the space below the text field.</p></li></ul><p>It generated code but not taking into consideration the latest changes I&#8217;ve applied to <em>ImageSearch</em> and its parent, so I&#8217;ve asked it to repeat with the latest code provided.</p><p>With the new generated code, I fixed a bug, and also passed the <em>exerciseName</em> from the parent to the <em>ImageSearch</em> component. Here is the value that ChatGPT added:</p><ul><li><p>Added validation for url and image url. Added Error Message for when Url is not a valid image</p></li><li><p>Called Google APIs instead of Pexels with placeholders for API_KEY and SEARCH_ENGINE_ID</p></li><li><p>Seemed to merge the two fields</p></li></ul><h4>Google Image Search via API</h4><p>It pointed out how to get the API_KEY, which was easy to generate. I asked it how to get SEARCH_ENGINE_ID, and it gave me the link, which I followed to create the &#8220;engine&#8221; to search images. On creation, it gave me the ID which I copied and pasted into the placeholder in my code.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!M2ae!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!M2ae!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png 424w, https://substackcdn.com/image/fetch/$s_!M2ae!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png 848w, https://substackcdn.com/image/fetch/$s_!M2ae!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png 1272w, https://substackcdn.com/image/fetch/$s_!M2ae!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!M2ae!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png" width="800" height="822" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:822,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!M2ae!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png 424w, https://substackcdn.com/image/fetch/$s_!M2ae!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png 848w, https://substackcdn.com/image/fetch/$s_!M2ae!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png 1272w, https://substackcdn.com/image/fetch/$s_!M2ae!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a1003f-90d6-4c7a-b0d7-62bcf9692052_800x822.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Creating a new Search Engine for Google API Calls</figcaption></figure></div><p>Now that I&#8217;ve done that, Google Search works!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wBfx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wBfx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png 424w, https://substackcdn.com/image/fetch/$s_!wBfx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png 848w, https://substackcdn.com/image/fetch/$s_!wBfx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png 1272w, https://substackcdn.com/image/fetch/$s_!wBfx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wBfx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png" width="800" height="1116" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1116,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!wBfx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png 424w, https://substackcdn.com/image/fetch/$s_!wBfx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png 848w, https://substackcdn.com/image/fetch/$s_!wBfx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png 1272w, https://substackcdn.com/image/fetch/$s_!wBfx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27e314d1-1b0e-484d-9622-191c9b0942a0_800x1116.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Searching Google for Images</figcaption></figure></div><p>However, It seems to have lost the behavior to hide the gallery when an image is selected.</p><h4>Image Url Preview</h4><p>Pasting a link in the search box magically previews the image, so there is at least also a win on that front.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!enJ-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!enJ-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png 424w, https://substackcdn.com/image/fetch/$s_!enJ-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png 848w, https://substackcdn.com/image/fetch/$s_!enJ-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png 1272w, https://substackcdn.com/image/fetch/$s_!enJ-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!enJ-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png" width="800" height="610" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/db4b9287-90fb-4114-ab03-611fc2712f32_800x610.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:610,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!enJ-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png 424w, https://substackcdn.com/image/fetch/$s_!enJ-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png 848w, https://substackcdn.com/image/fetch/$s_!enJ-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png 1272w, https://substackcdn.com/image/fetch/$s_!enJ-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb4b9287-90fb-4114-ab03-611fc2712f32_800x610.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Preview of a Pasted Image Url.</figcaption></figure></div><p><strong>Side Note</strong><em><strong>: </strong>The above is a picture of Portugal&#8217;s Sporting Club taken at some point in time. I quickly recognized player number 8, Bruno Fernandes. He joined Manchester United in January 2020 and has since become an integral part of the team&#8217;s midfield. Before joining Manchester United, Fernandes had a successful career at Sporting Club, where he won the Primeira Liga and the Ta&#231;a de Portugal in the 2018&#8211;19 season.</em></p><h4>Url Image Validation</h4><p>Another win is showing an error message when something looks like a URL but is not a valid image url.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Lp66!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Lp66!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png 424w, https://substackcdn.com/image/fetch/$s_!Lp66!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png 848w, https://substackcdn.com/image/fetch/$s_!Lp66!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png 1272w, https://substackcdn.com/image/fetch/$s_!Lp66!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Lp66!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png" width="800" height="541" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:541,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Lp66!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png 424w, https://substackcdn.com/image/fetch/$s_!Lp66!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png 848w, https://substackcdn.com/image/fetch/$s_!Lp66!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png 1272w, https://substackcdn.com/image/fetch/$s_!Lp66!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e7022e0-3bea-4cfa-b727-2df0ac8db8da_800x541.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Validating that the Url is an Image</figcaption></figure></div><h4>Hide Gallery on Image Selection</h4><p>I asked ChatGPT to hide the gallery when an image is selected. It introduced a <em>showGallery</em> state that I plugged into the code.</p><h4>Improved Image Validation</h4><p>When I select an image though, it says it&#8217;s invalid. I told ChatGPT that &lt;copied url&gt; is a valid image url but I am getting a validation error on it. I got the answer below and I updated the code accordingly using the original function name.</p><blockquote><p>Apologies for the confusion earlier. It seems that the isImageUrl function is unable to validate the image URL you provided. To fix this issue, you can use a more robust approach to determine if the URL points to an image. You can do this by fetching the image and checking the content type of the response.</p><p>Here&#8217;s the updated validateImageUrl function using this approach.</p></blockquote><h4>Multiple Searches</h4><p>Another bug I found was, when an image is selected, and I clear the search box and then try to search, the behavior of &#8220;searching&#8221; seems to be no longer active. I told that to ChatGPT and it gave me the fix described below. The fix didn&#8217;t create the desired behavior, so I looked at the code and made the appropriate fix. Following ChatGPT blindly in this case would have created more problems than solved.</p><blockquote><p>You&#8217;re right. The issue occurs because the gallery is not shown again when you start searching after clearing the search box. To fix this, you can update the useEffect hook that triggers the search to also set showGallery to true when the searchText changes</p></blockquote><p><strong>Note</strong>: it turns out there was a bug with this code and an unnecessary state (<em>showGallery</em>) being used.</p><h4>Debouncing</h4><p>Another thing I do not like about the experience is the fact that the UI refreshes the list of images as you type, which creates a weird flickering effect. As a result, I told ChatGPT to only apply the search when the user pauses typing, and it gave me the debounce code, which I applied successfully.</p><h4>Pagination</h4><blockquote><p>Next, I would like to be able to let the user move between pages of the image gallery.</p></blockquote><p>I gave that to ChatGPT, and it gave me the code including installing the @mui/lab NPM package. Luckily, I knew better to tell ChatGPT that I want to use Pagination from @mui/material not @mui/labs.</p><p>I plugged in the code, and I hit the error where variable <em>totalPages</em> does not exist, and when I asked ChatGPT, I got what I wanted.</p><p>I now have pages for navigation. However, the max page number is so high, when I click on it, Google seems to ignore my search.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3IYC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3IYC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png 424w, https://substackcdn.com/image/fetch/$s_!3IYC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png 848w, https://substackcdn.com/image/fetch/$s_!3IYC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png 1272w, https://substackcdn.com/image/fetch/$s_!3IYC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3IYC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png" width="800" height="950" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:950,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3IYC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png 424w, https://substackcdn.com/image/fetch/$s_!3IYC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png 848w, https://substackcdn.com/image/fetch/$s_!3IYC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png 1272w, https://substackcdn.com/image/fetch/$s_!3IYC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83229e4-10d2-42d2-be53-e9f174d92a40_800x950.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image Search Pagination</figcaption></figure></div><p>I&#8217;m thinking just choose a min between 1000 and total pages, and see if that practically does the job for what I am looking for. Even with that, Google is returning back to me an HTTP 400 when I try to access page 1000. Maybe I should just update the Pagination behavior to just navigate the next page rather than allow navigation to the max page. ChatGPT helped me get that done.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qMTH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qMTH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png 424w, https://substackcdn.com/image/fetch/$s_!qMTH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png 848w, https://substackcdn.com/image/fetch/$s_!qMTH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png 1272w, https://substackcdn.com/image/fetch/$s_!qMTH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qMTH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png" width="800" height="254" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d841d404-c6b7-4716-909a-684f01dd492d_800x254.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:254,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qMTH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png 424w, https://substackcdn.com/image/fetch/$s_!qMTH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png 848w, https://substackcdn.com/image/fetch/$s_!qMTH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png 1272w, https://substackcdn.com/image/fetch/$s_!qMTH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd841d404-c6b7-4716-909a-684f01dd492d_800x254.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Google Image Search, page by page</figcaption></figure></div><p>If I search for something, go to page 5, then search for something else, the page is not reset to 1. I fixed that myself by resetting <em>currentPage</em> back to 1 every time the <em>searchText</em> field changes.</p><h4>Considering Infinite Scrolling</h4><p>Another issue was the fact the UI jumps back to the top every time I change the page, so I thought I might as well replace pagination with infinite scrolling. I have ChatGPT&#8217;s help after all! Here is what it told me to do to transition to infinite scrolling:</p><blockquote><p>To replace the Pagination logic with infinite scrolling, you can use the IntersectionObserver API to detect when the user has scrolled to the bottom of the search results. Here&#8217;s how you can modify the ImageSearch component to implement infinite scrolling:</p><p>- Remove the Pagination component and related state variables (i.e., currentPage and totalPages).<br>- Create a new state variable to track the loading state of the search results:<br>- Create a reference for the element that will trigger the loading of more results when it becomes visible:<br>- Create a function that will load more results and append them to the current search results:<br>- Update the searchImages function to return the fetched results instead of setting the state directly:<br>- Set up an IntersectionObserver in a useEffect hook to observe the loadMoreRef element and trigger the loadMore function when it becomes visible:<br>- Add a div element as a child of the Grid container with a ref to loadMoreRef. This element will trigger the loading of more results when it becomes visible:<br>- Optionally, display a loading spinner when more results are being loaded:</p></blockquote><p>The code had a lot of issues, to begin with, it was pulling the same images for every page. I decided to just skip infinite scrolling and display 6 images at a time and show the pagination above the gallery.</p><p><em><strong>April 2nd ~2pm </strong></em>&#128172; :<em> Few hours passed, my wife is starting to get frustrated with me stuck on a laptop while we&#8217;re on vacation! It&#8217;s time to go do some exploration in Lisbon!</em></p><h4>Image Url State</h4><p><em><strong>April 2nd ~7:30 pm </strong></em>&#128172; &#129782;<em><strong>: </strong>Back from another exploration going the other way in the neighborhood.</em></p><p>I&#8217;ve discovered that the image url set in the <em>ImageSearch</em> component is not propagating to the parent component, so I fixed that.</p><p>I also refactored the code by removing some unnecessary states like <em>showGallery</em> and <em>selectedImage</em>. I think I picked those up from ChatGPT without paying much attention that the code could be written without them.</p><p>Again, when the image field was cleared, the imageUrl in the parent was not being reset to empty. Those are some of the details you&#8217;re likely to miss when you end up relying too much on ChatGPT.</p><h4>Move Video Url to its own tab</h4><p>In preparation to work next on Video, I decided to create a new tab &#8220;Video&#8221; and move that field there.</p><h4>Better Image Validation</h4><p>As I was testing, I noticed that the <em>isImageURL</em> logic that I&#8217;m using sometimes thinks an image is valid, even when it doesn&#8217;t load on a web page. Ex: <a href="https://www.hotelzaza.com/hs-fs/hubfs/ZaZa-HOU-CONCEPT-SUITE-AnAffairToRemember.jpe">https://www.hotelzaza.com/hs-fs/hubfs/ZaZa-HOU-CONCEPT-SUITE-AnAffairToRemember.jpe</a>.</p><p>I changed the behavior of validation, but that was not enough. Given that the image validation function is <em>async</em>, and it was being called in <em>useEffect</em> as a synchronous function, this was creating some unexpected behavior. Apparently, ChatGPT missed that. So I defined a new async function within useEffect and managed to find a way to get it to work.</p><p>Another situation where relying initially on ChatGPT could cause unexpected issues down the line.</p><h4>Storing Google API Keys safely</h4><p>ChatGPT plugged the Google API secrets in code. With its help, I moved it to NextJS environment variables.</p><h4>Automatically searching based on the provided exercise name</h4><p>If the user provides an exercise name and the Image Url isn&#8217;t already set, I would like to automatically populate the Image Search field with the exercise name and automatically search for it. Done, and you probably know by now who helped me out.</p><h4>Knowing when the user should select an image</h4><p>Next, I&#8217;d like to make it easy for the user to know when an image is selected.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DRDK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DRDK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png 424w, https://substackcdn.com/image/fetch/$s_!DRDK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png 848w, https://substackcdn.com/image/fetch/$s_!DRDK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png 1272w, https://substackcdn.com/image/fetch/$s_!DRDK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DRDK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png" width="800" height="822" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:822,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DRDK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png 424w, https://substackcdn.com/image/fetch/$s_!DRDK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png 848w, https://substackcdn.com/image/fetch/$s_!DRDK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png 1272w, https://substackcdn.com/image/fetch/$s_!DRDK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9498766-5106-4da3-97d6-9a08c7f5fa56_800x822.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Indicator for Image Selection</figcaption></figure></div><p>And when they search in the gallery, I want them to know that they can select an image from the gallery.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4m29!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4m29!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png 424w, https://substackcdn.com/image/fetch/$s_!4m29!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png 848w, https://substackcdn.com/image/fetch/$s_!4m29!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png 1272w, https://substackcdn.com/image/fetch/$s_!4m29!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4m29!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png" width="800" height="857" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:857,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4m29!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png 424w, https://substackcdn.com/image/fetch/$s_!4m29!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png 848w, https://substackcdn.com/image/fetch/$s_!4m29!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png 1272w, https://substackcdn.com/image/fetch/$s_!4m29!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d3e70bc-d43d-4f13-b731-fffff0959963_800x857.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Hint to &#8220;Select&#8221; an Image</figcaption></figure></div><h4>Image Upload Behavior to Firebase storage</h4><p>The one last very visible experience that&#8217;s not working is the ability to upload an image. I fixed that and also showed an error message when upload fails. This time, without ChatGPT&#8217;s help.</p><h4>Google API Safe Search</h4><p>I also realized I need to turn SafeSearch on, which I did from the Search engine settings I&#8217;ve created earlier.</p><p>However, even after a few days, I was able to search for unsafe things. I asked ChatGPT.</p><blockquote><p>The Google Custom Search API sometimes may not fully respect the SafeSearch setting of the Custom Search Engine (CSE) configuration. In such cases, you can enforce SafeSearch by adding the safe parameter directly in your API requests.</p><p>To enforce SafeSearch in your API requests, set the safe parameter to active:</p><p>However, please note that SafeSearch is not perfect, and there might still be some explicit content that slips through the filter. It&#8217;s always a good idea to have additional measures in place if content safety is crucial for your application.</p></blockquote><p>Although content safety is not paramount, I still prefer to ensure its protection. Therefore, I took the necessary steps to make the change, and it successfully resolved the issue.</p><div><hr></div><h3>YouTube Video Experience</h3><p>Who would want to provide a video with this experience? Probably, no one.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!j4ZD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j4ZD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png 424w, https://substackcdn.com/image/fetch/$s_!j4ZD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png 848w, https://substackcdn.com/image/fetch/$s_!j4ZD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png 1272w, https://substackcdn.com/image/fetch/$s_!j4ZD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j4ZD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png" width="800" height="393" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:393,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!j4ZD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png 424w, https://substackcdn.com/image/fetch/$s_!j4ZD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png 848w, https://substackcdn.com/image/fetch/$s_!j4ZD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png 1272w, https://substackcdn.com/image/fetch/$s_!j4ZD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb2d9cee-cbb0-4dcd-b363-fdfc40814d19_800x393.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Video Tab</figcaption></figure></div><p>I&#8217;m not going to enable any file upload capabilities. Instead, if I make it really easy for a user to find a YouTube video, then I&#8217;ve achieved my goal.</p><p>I can start to imagine what this looks like, but what if I pass it on to ChatGPT and see what it comes up with.</p><p>It generated a new component to search YouTube via API. The logic was insecurely done on the client side (exposes API key), so I instructed it to move it to the server side. It generated a new API route in NextJS with the logic to search YouTube for videos given a search keyword. The url being hit in the React component changed from <a href="https://www.googleapis.com/youtube/v3/search?part=snippet&amp;q=$%7Bquery%7D&amp;type=video&amp;key=$%7BAPI_KEY">https://www.googleapis.com/youtube/v3/search?part=snippet&amp;q=${query}&amp;type=video&amp;key=${API_KEY</a>} to <em>/api/youtube-search?query=${query}</em>.</p><p>Here are the YouTube search results.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!T_qa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!T_qa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png 424w, https://substackcdn.com/image/fetch/$s_!T_qa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png 848w, https://substackcdn.com/image/fetch/$s_!T_qa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png 1272w, https://substackcdn.com/image/fetch/$s_!T_qa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!T_qa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png" width="800" height="568" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:568,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!T_qa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png 424w, https://substackcdn.com/image/fetch/$s_!T_qa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png 848w, https://substackcdn.com/image/fetch/$s_!T_qa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png 1272w, https://substackcdn.com/image/fetch/$s_!T_qa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd8a16f8-d0bc-47b0-b13d-f98305b6b661_800x568.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">YouTube Search Results</figcaption></figure></div><p>When an item is selected in the list, the video name is passed back from the Dialog back to the Video tab.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e0gR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e0gR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png 424w, https://substackcdn.com/image/fetch/$s_!e0gR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png 848w, https://substackcdn.com/image/fetch/$s_!e0gR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png 1272w, https://substackcdn.com/image/fetch/$s_!e0gR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e0gR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png" width="800" height="618" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/21486adf-b129-43bb-b22a-73104d18470f_800x618.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:618,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e0gR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png 424w, https://substackcdn.com/image/fetch/$s_!e0gR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png 848w, https://substackcdn.com/image/fetch/$s_!e0gR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png 1272w, https://substackcdn.com/image/fetch/$s_!e0gR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21486adf-b129-43bb-b22a-73104d18470f_800x618.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Video Item Selection</figcaption></figure></div><p>I asked GPT to generate thumbnails for the videos.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4sDx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4sDx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png 424w, https://substackcdn.com/image/fetch/$s_!4sDx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png 848w, https://substackcdn.com/image/fetch/$s_!4sDx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png 1272w, https://substackcdn.com/image/fetch/$s_!4sDx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4sDx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png" width="800" height="532" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9592cd44-acf0-45de-bf09-e72736b42875_800x532.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:532,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4sDx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png 424w, https://substackcdn.com/image/fetch/$s_!4sDx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png 848w, https://substackcdn.com/image/fetch/$s_!4sDx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png 1272w, https://substackcdn.com/image/fetch/$s_!4sDx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9592cd44-acf0-45de-bf09-e72736b42875_800x532.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">YouTube Video Item Thumbnail</figcaption></figure></div><blockquote><p>I want the thumbnails to be larger and have the Youtube play button on them. When clicked, I would like to be able to play the video in a small popup dialog. I would also like to add a &#8220;Select&#8221; button under each thumbnail to actually enable the selection of the video.</p></blockquote><p>So I asked ChatGPT, and I updated the component after I installed <em>react-player</em> via NPM.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hRx2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hRx2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png 424w, https://substackcdn.com/image/fetch/$s_!hRx2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png 848w, https://substackcdn.com/image/fetch/$s_!hRx2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png 1272w, https://substackcdn.com/image/fetch/$s_!hRx2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hRx2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png" width="800" height="543" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:543,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hRx2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png 424w, https://substackcdn.com/image/fetch/$s_!hRx2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png 848w, https://substackcdn.com/image/fetch/$s_!hRx2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png 1272w, https://substackcdn.com/image/fetch/$s_!hRx2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ac7808c-4a2a-4e08-b85b-844c85fbfb34_800x543.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The layout is weird. Clicking on a video opens a dialog with the thumbnail barely visible, and when clicked, it takes you to YouTube in a new tab.</p><p><em><strong>April 2nd ~ 9pm</strong></em> &#129782;: <em>I&#8217;m out. I need a break from all of this.</em></p><p><em><strong>April 3rd at 4 pm </strong></em>&#128084;<em>: Two hour work meeting, coupled with another 1&#8211;2 hours of work.</em></p><h4>Improving YouTube Video Experience</h4><p><em><strong>April 4th 1 am </strong></em>&#129782;<em><strong> </strong></em>&#128172;<em><strong>: </strong>After a full day of exploring, drinking, walking and eating in Lisbon, it&#8217;s 1 am, and I&#8217;m ready to write some code. I mean, have ChatGPT write me some code.</em></p><blockquote><p>Is my role in this as a programmer, with ChatGPT being the assistant? Or am I more of a Code Plugger?</p></blockquote><p>For that, I also asked ChatGPT.</p><blockquote><p>As for your role in this scenario, when working with ChatGPT, you can think of yourself as a programmer with ChatGPT being your AI assistant. You provide the high-level requirements and guidance, and ChatGPT helps you by generating code snippets or offering suggestions. The term &#8220;Code Plugger&#8221; isn&#8217;t a standard term in the industry, but if you prefer, you could use it to describe your role while working with ChatGPT.</p></blockquote><p>Or a Code Connector?</p><p>Here is what ChatGPT has to say about it.</p><blockquote><p>In summary, while &#8220;code connector&#8221; is not a standard term, it could be interpreted as a concept, tool, or method that helps connect different parts of code, modules, or systems within software development.</p></blockquote><p>Then I asked what if the Code Connector is a human?</p><blockquote><p>If a &#8220;code connector&#8221; were a human, it would be someone who plays a key role in integrating different parts of a software system or facilitating communication between different software components, teams, or platforms.</p></blockquote><p>Plugger or Connector, it&#8217;s time to move on and get productive getting things done!</p><blockquote><p>Here are the improvements I would like to make:</p><p>- Show the YouTube videos in a grid that is web responsive, it becomes more like a column on a mobile device<br>- When the video thumbnail is clicked, I would like to play the YouTube video within the thumbnail<br>- I would like the Play button on the YouTube video to be more visible</p></blockquote><p>Here are the changes ChatGPT recommended when I asked:</p><blockquote><p>Here&#8217;s an updated version of your code to improve the user experience as you requested:</p><p>- Display YouTube videos in a responsive grid that becomes a column on mobile devices.<br>- Play the YouTube video within the thumbnail when clicked.<br>- Make the play button more visible.</p><p>To achieve this, I&#8217;ve made the following changes:</p><p>- Imported Grid and GridList from @mui/material.<br>- Created a new CSS file named YouTubeSearchBox.module.css to style the components.<br>- Modified the ListItem component to use Grid and GridList for responsiveness.<br>- Updated the Play button to be more visible with a background color.</p></blockquote><p>There were some bugs. For example, ChatGPT imported <em>GridList</em> which does not exist in @mui/material, but it was able to fix that on prompting.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DvQq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DvQq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png 424w, https://substackcdn.com/image/fetch/$s_!DvQq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png 848w, https://substackcdn.com/image/fetch/$s_!DvQq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png 1272w, https://substackcdn.com/image/fetch/$s_!DvQq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DvQq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png" width="800" height="648" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:648,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DvQq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png 424w, https://substackcdn.com/image/fetch/$s_!DvQq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png 848w, https://substackcdn.com/image/fetch/$s_!DvQq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png 1272w, https://substackcdn.com/image/fetch/$s_!DvQq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2713f5f8-fba8-4cb0-af65-48e398335b57_800x648.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">YouTube Videos Grid</figcaption></figure></div><p>Playing the video still shows me this weird behavior.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QeSm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QeSm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png 424w, https://substackcdn.com/image/fetch/$s_!QeSm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png 848w, https://substackcdn.com/image/fetch/$s_!QeSm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png 1272w, https://substackcdn.com/image/fetch/$s_!QeSm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QeSm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png" width="800" height="652" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:652,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QeSm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png 424w, https://substackcdn.com/image/fetch/$s_!QeSm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png 848w, https://substackcdn.com/image/fetch/$s_!QeSm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png 1272w, https://substackcdn.com/image/fetch/$s_!QeSm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21dc4986-f8ee-460f-bfdc-77606976ff5c_800x652.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Weird Experience Playing YouTube Video</figcaption></figure></div><blockquote><p>Some additional things I would like to change:</p><p>- On clicking the button to play the video, I want the video to play within the thumbnail. It might be better to just iframe the YouTube video rather than using react-player/youtube.<br>- I would like the SELECT buttons to be horizontally centered.</p></blockquote><p>ChatGPT told me:</p><blockquote><p>I&#8217;ve made the requested changes:</p><p>- Replaced react-player/youtube with an iframe to play the video within the thumbnail.<br>- Horizontally centered the &#8220;Select&#8221; buttons.</p></blockquote><p>The result is a mess. I&#8217;ve decided to do it myself at this point. I fixed the issue below.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Eih2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Eih2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png 424w, https://substackcdn.com/image/fetch/$s_!Eih2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png 848w, https://substackcdn.com/image/fetch/$s_!Eih2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png 1272w, https://substackcdn.com/image/fetch/$s_!Eih2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Eih2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png" width="800" height="507" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bef12343-755d-404b-abed-56fd2b5ebd22_800x507.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:507,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Eih2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png 424w, https://substackcdn.com/image/fetch/$s_!Eih2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png 848w, https://substackcdn.com/image/fetch/$s_!Eih2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png 1272w, https://substackcdn.com/image/fetch/$s_!Eih2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbef12343-755d-404b-abed-56fd2b5ebd22_800x507.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Video Playing Below Thumbnail!</figcaption></figure></div><p>Next, I want the YouTube title to be in a smaller font, and to use the &lt;Link&gt; NexTJS component to open the YouTube video in a new tab. I asked ChatGPT and I got something with an error, which it then fixed on prompting.</p><p>I then requested ChatGPT to make the SELECT an animated button and place all the SELECT buttons in the Grid on the same line. It went too fancy, importing @mui/system component. I tried again: Improve the look &amp; feel of the SELECT button (add background) and make them all show on the same line. The UI looked malformed, so I made some edits and ended up with this.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mQeq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mQeq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png 424w, https://substackcdn.com/image/fetch/$s_!mQeq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png 848w, https://substackcdn.com/image/fetch/$s_!mQeq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png 1272w, https://substackcdn.com/image/fetch/$s_!mQeq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mQeq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png" width="800" height="386" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/20539452-92e3-416d-bee6-ba4c32178273_800x386.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:386,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mQeq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png 424w, https://substackcdn.com/image/fetch/$s_!mQeq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png 848w, https://substackcdn.com/image/fetch/$s_!mQeq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png 1272w, https://substackcdn.com/image/fetch/$s_!mQeq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20539452-92e3-416d-bee6-ba4c32178273_800x386.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Improved YouTube Video Selection</figcaption></figure></div><p>Shortly after, I stopped seeing any YouTube results. I think the API is probably blocking me after all the requests I&#8217;ve made. As a quick way to investigate, I asked ChatGPT to update my NextJS API to generate mock videos if I pass a &#8220;mock&#8221; parameter to it.</p><p>Ok, this proved there is something off with the YouTube API, but I&#8217;ll leave dealing with it to another time.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cvoX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cvoX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png 424w, https://substackcdn.com/image/fetch/$s_!cvoX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png 848w, https://substackcdn.com/image/fetch/$s_!cvoX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png 1272w, https://substackcdn.com/image/fetch/$s_!cvoX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cvoX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png" width="800" height="271" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:271,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cvoX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png 424w, https://substackcdn.com/image/fetch/$s_!cvoX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png 848w, https://substackcdn.com/image/fetch/$s_!cvoX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png 1272w, https://substackcdn.com/image/fetch/$s_!cvoX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F268e7cbd-f791-4bc0-9cf2-e31b5e50fb8e_800x271.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>Searching In Place</h4><p>Right now, the video lookup behavior is weird. It was all ChatGPT&#8217;s touch.</p><p>Instead of opening a dialog when a user clicks on the &#8220;Search YouTube Videos&#8221; text box, I would to like to</p><ul><li><p>Show a search icon in the &#8220;Search YouTube Videos&#8221; field</p></li><li><p>As the user starts typing, with debouncing, and instead of opening a separate dialog, show the Grid of YouTube videos directly under the search box.</p></li></ul><p>When a user clicks the &#8220;SELECT&#8221; button:</p><ul><li><p>Update the &#8220;Search YouTube Videos&#8221; field with the URL of the YouTube Video</p></li><li><p>hide the YouTube grid</p></li><li><p>Show the thumbnail (75% width) of the selected video</p></li><li><p>Show italic text under the video that says: Selected Video &#8220;video Id&#8221; successfully, where &#8220;video Id&#8221; is the youTube id of the video</p></li><li><p>When there is text in the field, show a &#8220;clear&#8221; button. When clicked, it would clear the text in the field and resets the search.</p></li><li><p>When the user enters a valid url, validate that the url points to a youtube video. If it does, preview the Youtube video in the space below the text field. If it is a url that does not point to a Youtube video, show an error message.</p></li><li><p>The user should be able to navigate the Youtube grid in pages.</p></li></ul><p>First, I provided ChatGPT with the latest code of <em>ExerciseSuggestion</em>, and then requested the changes above. The change was a little bit of a shit show with a lot of my &#8220;hard-earned&#8221; code that I previously wrote removed. It also was not allowing me to paste the whole code of <em>YouTubeSearchBox.tsx</em> so it can make the suggestions based on what&#8217;s already there. For that reason, I&#8217;ve decided to feed ChatGPT the changes I need one by one.</p><p>I tried again, and I was able to paste the code, and here is what it said:</p><blockquote><p>Based on your latest code, I have made the required changes to implement the features you requested:</p><p>- Show a search icon in the &#8220;Search YouTube Videos&#8221; field<br>- Show the Grid of YouTube videos directly under the search box with debouncing<br>- Update the &#8220;Search YouTube Videos&#8221; field with the URL of the YouTube Video upon selection<br>- Hide the YouTube grid and show the thumbnail of the selected video<br>- Show italic text under the video with the selected video ID<br>- Add a &#8220;clear&#8221; button when there is text in the field<br>- Validate the URL and preview the YouTube video when a valid URL is entered<br>- Show an error message when the URL does not point to a YouTube video<br>- Add pagination for the YouTube grid</p></blockquote><p>Here is the experience.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pZUn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pZUn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png 424w, https://substackcdn.com/image/fetch/$s_!pZUn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png 848w, https://substackcdn.com/image/fetch/$s_!pZUn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png 1272w, https://substackcdn.com/image/fetch/$s_!pZUn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pZUn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png" width="800" height="676" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:676,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pZUn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png 424w, https://substackcdn.com/image/fetch/$s_!pZUn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png 848w, https://substackcdn.com/image/fetch/$s_!pZUn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png 1272w, https://substackcdn.com/image/fetch/$s_!pZUn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d89aa63-45b2-4f44-80a9-02a24352279d_800x676.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">YouTube Videos Grid Layout</figcaption></figure></div><p>When I click &#8220;Select&#8221;, some of the capabilities are there.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yO4u!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yO4u!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png 424w, https://substackcdn.com/image/fetch/$s_!yO4u!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png 848w, https://substackcdn.com/image/fetch/$s_!yO4u!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png 1272w, https://substackcdn.com/image/fetch/$s_!yO4u!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yO4u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png" width="800" height="468" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:468,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yO4u!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png 424w, https://substackcdn.com/image/fetch/$s_!yO4u!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png 848w, https://substackcdn.com/image/fetch/$s_!yO4u!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png 1272w, https://substackcdn.com/image/fetch/$s_!yO4u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b37d0c8-1ae1-48c6-98a3-c8d956721d68_800x468.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">YouTube Video Selection</figcaption></figure></div><p>Also, there are bugs where once I search, additional searches do not work. In fact, I have a good amount of tweaking to do, and I am tired.</p><p><em><strong>April 4th </strong></em>&#128172;<em><strong>: </strong>I&#8217;ve spent 2 hours since 1 am working on this. I&#8217;m starting to wonder whether this session was productive at all.</em></p><p>Could I have done better if I did this without ChatGPT&#8217;s help? Maybe if I were more proficient in TypeScript, React and NextJS?</p><h4>YouTube Search Experience</h4><p><em><strong>April 4th </strong></em>&#128172;<em><strong>: </strong>I woke up a little earlier than expected. It&#8217;s 10:30 am now.</em></p><p>The first thing I want to fix is the layout. I tried a few prompts with ChatGPT but I did not get what I wanted. However, I got the idea of changing the Dialog maxWidth to &#8220;md&#8221;, and that seems to resolve the issue.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vvVY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vvVY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png 424w, https://substackcdn.com/image/fetch/$s_!vvVY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png 848w, https://substackcdn.com/image/fetch/$s_!vvVY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png 1272w, https://substackcdn.com/image/fetch/$s_!vvVY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vvVY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png" width="800" height="424" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:424,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vvVY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png 424w, https://substackcdn.com/image/fetch/$s_!vvVY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png 848w, https://substackcdn.com/image/fetch/$s_!vvVY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png 1272w, https://substackcdn.com/image/fetch/$s_!vvVY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20f2742a-5923-4e24-ac0b-bdb3cc7cc57d_800x424.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Good spacing between YouTube Video Thumbnails</figcaption></figure></div><p>Next, I moved the Clear &#8220;X&#8221; button inside the Search box. I also added a little bit of space after the Search icon. I got the gallery to disappear when the Clear button is clicked. Those were very quick changes; it would have probably taken more time asking ChatGPT for help.</p><p>Next issue I have is whenever I change the Search term, the list of videos do not refresh. Only after clearing the Search box will the actual searching become effective. I removed the lodash debouncing and created a custom useDebounce hook and that seems to do the magic. The best way to validate is to remove the &#8220;mock&#8221; videos and try the search on real YouTube videos. Alright, it looks like it worked out!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oEGz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oEGz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png 424w, https://substackcdn.com/image/fetch/$s_!oEGz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png 848w, https://substackcdn.com/image/fetch/$s_!oEGz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png 1272w, https://substackcdn.com/image/fetch/$s_!oEGz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oEGz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png" width="800" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!oEGz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png 424w, https://substackcdn.com/image/fetch/$s_!oEGz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png 848w, https://substackcdn.com/image/fetch/$s_!oEGz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png 1272w, https://substackcdn.com/image/fetch/$s_!oEGz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fb09cd2-e744-403d-af6b-4fb50fddb81f_800x504.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Video Search Debouncing</figcaption></figure></div><p>One other bug I found, if I paste a youTube video url in the search box, I get both the gallery and selected video to be shown.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!T1v1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!T1v1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png 424w, https://substackcdn.com/image/fetch/$s_!T1v1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png 848w, https://substackcdn.com/image/fetch/$s_!T1v1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png 1272w, https://substackcdn.com/image/fetch/$s_!T1v1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!T1v1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png" width="800" height="1134" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1134,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!T1v1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png 424w, https://substackcdn.com/image/fetch/$s_!T1v1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png 848w, https://substackcdn.com/image/fetch/$s_!T1v1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png 1272w, https://substackcdn.com/image/fetch/$s_!T1v1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ead7b9f-a433-41ff-a311-ec18ae913dee_800x1134.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Selected Video Bug</figcaption></figure></div><p>I went ahead and fixed this bug and other state-related bugs without leaning on ChatGPT.</p><h4>Auto-Search Based on Exercise Name</h4><p>If the user goes to the video tab, and the search box is empty, I would like it to get automatically populated with the &#8220;Exercise Name&#8221; set in the About Tab. This is similar to the behavior I built in the image tab, so I just looked up the logic from there rather than relying on ChatGPT.</p><h4>YouTube API Rate Limiting</h4><p>I am calling the YouTube Data API from my backend, so I&#8217;m concerned that I will be blocked if there is enough usage of the feature. I asked ChatGPT how many searches I can do per day:</p><blockquote><p>When using the YouTube Data API&#8217;s search functionality, each search request consumes 100 units of quota from your daily allocation.</p><p>For example, if you have the default daily quota of 10,000 units, you can make up to 100 search requests in a single day before reaching your limit (10,000 units / 100 units per search request = 100 search requests).</p><p>Remember that the quota usage can change over time, so it&#8217;s always a good idea to check the YouTube API documentation and your Google Cloud Console for the latest information on quota costs and your project&#8217;s quota usage.</p></blockquote><p>It does look like I would easily get to my daily limit, with just 100 searches a day! The path forward is a little complicated, based on <a href="https://developers.google.com/youtube/v3/guides/quota_and_compliance_audits">this page</a> from Google. I went through a very painful form that Google had me fill to get more quota, let&#8217;s hope somebody at Google acknowledges it.</p><p><em><strong>Update from the Future (April 9th)</strong>: I haven&#8217;t heard anything back from Google about increasing the limit.</em></p><p><em><strong>April 4th </strong></em>&#129782;<em><strong>: </strong></em>Now, it&#8217;s time to go do other stuff in life. I&#8217;m in Portugal after all!</p><div><hr></div><h3>Current Exercise Data Model</h3><p><em><strong>April 4th 3:30 pm </strong></em>&#128172;<em><strong>: </strong>Back.</em></p><p>I think now we&#8217;re getting to the point of all of this work! When someone requests an exercise, I&#8217;d like to make it as easy as possible to plug the suggestion into </p><p>https://catalog.handstandquest.com/</p><p> and more importantly, into the <a href="https://apps.apple.com/us/app/handstand-quest/id1482090288">Handstand Quest iOS App</a>!</p><p>For that to be as smooth as possible, when an exercise request is submitted, I want the format of the request to be exactly like the one I have in the iOS app.</p><p>Here is a sample JSON used in the app for the handstand exercise. This gets read on app launch and gets serialized into a Swift object when the app starts.</p><pre><code>{
  "id": "Handstand",
  "name": "Handstand",
  "category": 3,
  "description": "Before starting:\n- make sure you warm up your wrists and stretch your shoulders.\n- be comfortable with bailing out of a handstand (ex: cartwheel)\n\nPlace your hands on the floor, kick with your dominant leg.\n\nMake sure to focus on getting your pelvis stacked over the shoulders and wrist, as your kick up and when you reach up. Make sure your arms are straight and core engaged.\n\nBreathe and know when you need to stop to avoid injuries.",
  "tenthSecondRepInterval": 50,
  "pageId": 1,
  "met": 10.0,
  "voiceCommands": [
    {
      "title": "handstand",
      "id": 1
    }
  ],
  "tips": [
    {
      "title": "Form follows function",
      "body": "Cambered hands, active shoulders, locked elbows, hips over head, feet over hips&#8230; really whatever feels easier to get you to hold the handstand longer."
    },
    {
      "title": "Make it automatic",
      "body": "By doing countless handstands, we get from conscious to automatic brain behavior. It starts becoming more like driving, and thus a lot easier to hold."
    },
    {
      "title": "Regaining balance",
      "body": "Lose balance =&gt; correct the flow =&gt; recover. Real progress comes from struggling to correct your balance by squeezing your body and fingers tightly in an attempt to recover."
    }
  ],
  "subcategory": "Handstand Variations",
  "metricType": 0,
  "hasDemo": true,
  "hasHowTo": true,
  "howToYouTube": "KNC5lkoE2Fs"
}</code></pre><p>It would be also worthwhile to share a visual of the current experience I have in the mobile app to edit a builtin exercise or create a custom exercise.</p><p>The About, Media and Tips views in the mobile app are very similar to the ones we are building in this Web App.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!f5TN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!f5TN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!f5TN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!f5TN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!f5TN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!f5TN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png" width="400" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!f5TN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!f5TN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!f5TN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!f5TN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f12f190-7328-46ad-900c-52e7b1cd698c_400x867.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mAs2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mAs2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!mAs2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!mAs2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!mAs2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mAs2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png" width="400" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mAs2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!mAs2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!mAs2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!mAs2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7036bb3e-4ca3-4cbf-8ac5-a203d57fb21d_400x867.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AGTv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AGTv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!AGTv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!AGTv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!AGTv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AGTv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png" width="400" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AGTv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!AGTv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!AGTv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!AGTv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fc9d72e-85e0-4219-8c8c-5299a16dc588_400x867.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">About, Media, Settings</figcaption></figure></div><p>The below Settings and &#8220;Voice Commands&#8221; views allow the user to configure their experience in the mobile app. For the most part, they are currently not related to this web app, except for the MET field in settings, which maps to &#8220;Intensity Level&#8221; in the web app.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qcx5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qcx5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!qcx5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!qcx5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!qcx5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qcx5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png" width="600" height="1301" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1301,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qcx5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!qcx5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!qcx5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!qcx5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53414c53-6b33-4f4e-92e3-73011c8f5b3e_600x1301.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!E30k!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E30k!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!E30k!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!E30k!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!E30k!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!E30k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png" width="600" height="1301" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d13a9525-1e01-439c-beba-d7790423140c_600x1301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1301,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!E30k!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!E30k!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!E30k!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!E30k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd13a9525-1e01-439c-beba-d7790423140c_600x1301.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Settings, Voice Commands</figcaption></figure></div><p>Here is how the fields in the &#8220;Request Exercise&#8221; Form would map to the current JSON format I have in the app.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jfp2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jfp2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png 424w, https://substackcdn.com/image/fetch/$s_!jfp2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png 848w, https://substackcdn.com/image/fetch/$s_!jfp2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png 1272w, https://substackcdn.com/image/fetch/$s_!jfp2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jfp2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png" width="800" height="736" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:736,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jfp2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png 424w, https://substackcdn.com/image/fetch/$s_!jfp2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png 848w, https://substackcdn.com/image/fetch/$s_!jfp2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png 1272w, https://substackcdn.com/image/fetch/$s_!jfp2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b591c8f-ded9-4653-919c-6983a0fb27a0_800x736.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Mapping fields in &#8220;Request Exercise&#8221; form to JSON in the app</figcaption></figure></div><p>Fields in JSON but not in the &#8220;Request Exercise&#8221; Form. Find a way to set the fields behind the scenes when the &#8220;Request Exercise&#8221; Form is submitted.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!K4wj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K4wj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png 424w, https://substackcdn.com/image/fetch/$s_!K4wj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png 848w, https://substackcdn.com/image/fetch/$s_!K4wj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png 1272w, https://substackcdn.com/image/fetch/$s_!K4wj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!K4wj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png" width="800" height="593" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:593,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!K4wj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png 424w, https://substackcdn.com/image/fetch/$s_!K4wj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png 848w, https://substackcdn.com/image/fetch/$s_!K4wj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png 1272w, https://substackcdn.com/image/fetch/$s_!K4wj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86c70ccf-f65d-4470-95d6-ca33e86f7818_800x593.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Fields in JSON but not in the &#8220;Request Exercise&#8221; Form</figcaption></figure></div><div><hr></div><h3>Acting on the Exercise Suggestion</h3><p>For me to most effectively incorporate an exercise suggestion, I need it to be in a JSON format that matches the data model defined earlier. So if I generate the JSON and send it in an email or save it in storage as a JSON file, then I should be able to take action on it.</p><p>I would copy the JSON file content into a local JSON file that has the definition of all exercises. This file gets loaded by the mobile app. I then use an Electron app I wrote to generate an MD file from JSON to be loaded statically by this NextJS web app.</p><p>Because ChatGPT is capable of converting a JSON file to MD in a specific format, I could generate the MD file too, then either:</p><ul><li><p>Get the MD file pushed to the web app repository</p></li><li><p>Put the MD file in Google storage or email attachment so I can easily download it</p></li></ul><p>Either way, I will use my internal tool because it is free of cost to me.</p><p>Moving on, I&#8217;ll do the following: on submitting the exercise request, I will send myself an email with all the details nicely formatted in HTML, and towards the end of the HTML, I&#8217;ll include a link to the JSON file stored on Firebase Storage.</p><p><em><strong>April 5th at 8:30 am </strong></em>&#9917;<em>: The Washington EPD Boys (born 2009) team played their first game at the Iber Cup, winning 3&#8211;0. My kid made an assist. I was relieved since I wasn&#8217;t sure how he&#8217;ll be able to perform on a team 1 year older (he&#8217;s born 2010) and with players he&#8217;s never played with before as part of a team.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6wa5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6wa5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png 424w, https://substackcdn.com/image/fetch/$s_!6wa5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png 848w, https://substackcdn.com/image/fetch/$s_!6wa5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png 1272w, https://substackcdn.com/image/fetch/$s_!6wa5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6wa5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png" width="800" height="314" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:314,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6wa5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png 424w, https://substackcdn.com/image/fetch/$s_!6wa5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png 848w, https://substackcdn.com/image/fetch/$s_!6wa5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png 1272w, https://substackcdn.com/image/fetch/$s_!6wa5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32f2892-5a37-4743-8bcf-d13eddb77ac4_800x314.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://cascais.ibercup.com/en/matches/team/cat/1652">Washington Epd</a> vs <a href="https://cascais.ibercup.com/en/matches/team/cat/1602">Coerver RTBC B</a></figcaption></figure></div><p><em><strong>April 5th at 4 pm </strong></em>&#128084;<em>: Two hour wok meeting, coupled with another ~1 hour of work. Go get dinner, then spend another ~4 hours writing promotions doc.</em></p><h4>Generating the JSON</h4><p><em><strong>April 6th at 1 am </strong></em>&#128172;<em><strong>: </strong>Back.</em></p><p>I told ChatGPT to generate the JSON from the request form. I showed it a sample JSON and told it how to map the data as follows:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Of5o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Of5o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png 424w, https://substackcdn.com/image/fetch/$s_!Of5o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png 848w, https://substackcdn.com/image/fetch/$s_!Of5o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png 1272w, https://substackcdn.com/image/fetch/$s_!Of5o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Of5o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png" width="800" height="913" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:913,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Of5o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png 424w, https://substackcdn.com/image/fetch/$s_!Of5o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png 848w, https://substackcdn.com/image/fetch/$s_!Of5o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png 1272w, https://substackcdn.com/image/fetch/$s_!Of5o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc4b1458-695e-44f9-8399-2eed431a2c2c_800x913.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Mapping Recommended to ChatGPT</figcaption></figure></div><p>It did it out of context, so I gave it the React state variables in the file and it generated what I was looking for.</p><p>I&#8217;ve changed the submit button to be only enabled when an exercise name has been specified. When the user clicks submit, I generate the JSON and print it to the console window for now.</p><h4>Saving the JSON and getting its Download Url</h4><p>I would like to store the formatted generated JSON in Firebase storage. I&#8217;ve set the following security rules so that anyone can create on the backend but not overwrite an existing file.</p><pre><code>match /exercises/json/{ExerciseId}/{DateString} {
      allow create, read;
}</code></pre><p>With little refactoring to fetch exercise Id anytime based on the name, I asked ChatGPT and it generated the code.</p><h4>Generating the HTML and sending via Email</h4><p>I already have a mechanism in my system to enable sending email notifications. I leverage the <a href="https://extensions.dev/extensions/firebase/firestore-send-email">Trigger Email from Firestore</a> Firebase extension. So all I need to do is save documents in that location, and the extension will take care of sending the email.</p><p>I asked ChatGPT to generate the HTML from the JSON, then simply transformed that into an EmailMessage object that gets sent to a Firestore document, which ends up triggering the extension to send the email.</p><p>The email looks as follows:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!K7Ng!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K7Ng!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png 424w, https://substackcdn.com/image/fetch/$s_!K7Ng!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png 848w, https://substackcdn.com/image/fetch/$s_!K7Ng!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png 1272w, https://substackcdn.com/image/fetch/$s_!K7Ng!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!K7Ng!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png" width="800" height="558" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ebf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:558,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!K7Ng!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png 424w, https://substackcdn.com/image/fetch/$s_!K7Ng!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png 848w, https://substackcdn.com/image/fetch/$s_!K7Ng!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png 1272w, https://substackcdn.com/image/fetch/$s_!K7Ng!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febf546c2-770a-45b3-98d8-87d09eec29ad_800x558.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Sample Email Notification from an Exercise Request</figcaption></figure></div><div><hr></div><h3>Match Web App Colors</h3><p>I would like to replace all the blue in the MUI library with the Handstand Quest green color.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UJBg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UJBg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png 424w, https://substackcdn.com/image/fetch/$s_!UJBg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png 848w, https://substackcdn.com/image/fetch/$s_!UJBg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png 1272w, https://substackcdn.com/image/fetch/$s_!UJBg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UJBg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png" width="762" height="208" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:208,&quot;width&quot;:762,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UJBg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png 424w, https://substackcdn.com/image/fetch/$s_!UJBg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png 848w, https://substackcdn.com/image/fetch/$s_!UJBg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png 1272w, https://substackcdn.com/image/fetch/$s_!UJBg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd01fba1-6605-485a-bf7c-7df4e423bc00_762x208.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Blue button</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-VQP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-VQP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png 424w, https://substackcdn.com/image/fetch/$s_!-VQP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png 848w, https://substackcdn.com/image/fetch/$s_!-VQP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png 1272w, https://substackcdn.com/image/fetch/$s_!-VQP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-VQP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png" width="800" height="211" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:211,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-VQP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png 424w, https://substackcdn.com/image/fetch/$s_!-VQP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png 848w, https://substackcdn.com/image/fetch/$s_!-VQP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png 1272w, https://substackcdn.com/image/fetch/$s_!-VQP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff665e050-46e8-4ea7-ad91-3e8645f52010_800x211.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Blue Borders and Text</figcaption></figure></div><p>ChatGPT showed me how to create a custom theme and apply it to my application using the ThemeProvider component.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DRYI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DRYI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png 424w, https://substackcdn.com/image/fetch/$s_!DRYI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png 848w, https://substackcdn.com/image/fetch/$s_!DRYI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png 1272w, https://substackcdn.com/image/fetch/$s_!DRYI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DRYI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png" width="800" height="816" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:816,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DRYI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png 424w, https://substackcdn.com/image/fetch/$s_!DRYI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png 848w, https://substackcdn.com/image/fetch/$s_!DRYI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png 1272w, https://substackcdn.com/image/fetch/$s_!DRYI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a4977e-5144-4cfd-8fa6-79136a44b863_800x816.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Updated Look &amp; Feel via a Theme</figcaption></figure></div><div><hr></div><h3>Using GPT API to generate exercise data</h3><p>Once the user specifies an exercise name, automatically generate all the other exercise data. Users should then be able to update it however they desire and submit.</p><p>In addition to removing friction for users when suggesting an exercise, this is a pretty effective mechanism (internal tool) for me to continue to easily build out the exercise catalog over time, with curated quality content mostly generated by GPT.</p><p><em><strong>April 6th </strong></em>&#128172;<em><strong>: </strong>Let&#8217;s see how long building this capability would take. It&#8217;s 2:30 am. I&#8217;ve been actually working on this project for 1.5 hours. The 6 hours before that, working on mid-year reviews and promotion endorsements for my team at work.</em></p><p><em><strong>Side note</strong></em>: Here is some additional context on what I do. I have a full-time job as a manager, which I genuinely enjoy, particularly when it comes to collaborating with my team. However, I also feel a strong desire to pursue my passions and interests. As an engineer, I find great satisfaction in creating and building my own projects. It&#8217;s like a digital form of art or craftsmanship, akin to woodworking. Not only does this provide a sense of fulfillment, but it also has the potential to generate income. So, why not focus on these enjoyable and rewarding pursuits instead of spending time on activities that are less fulfilling and fun?</p><h4>Plugging in GPT-4 code</h4><p>Here is what I will instruct ChatGPT to do.</p><blockquote><p>Here is the React code for my exercise request form (just include fields in the About tab)</p><p>&lt;code not included for brevity&gt;</p><p>- When the user specifies an exercise name, I would like to surface a &#8220;Generate&#8221; button in the right side of the Exercise Name field<br>- When the user clicks the &#8220;Generate&#8221; button, I would like it to do the following:<br>&#8202;&#8212;&#8202;Call the GPT 4 API to get the category, subcategory, How To Instructions,<br>Intensity Level, and automatically update those fields with the response I get back from the GPT 4 API</p></blockquote><p>I got some useful code, some irrelevant, and some of my requests ignored. I guess it is too much to ask.</p><p><em><strong>April 6th 3:30 am </strong></em>&#128172;<em><strong>: </strong>One hour later, I am still getting HTTP 404 and 400 back from the API. I think this <a href="https://replit.com/@alibertine/GPT-4-Chat-UI#package.json">replit</a> looks like a reliable source to interact with OpenAI via NextJS App.</em></p><p><em><strong>April 6th 9:40 am </strong></em>&#9917;<em>: The soccer team had a draw with <a href="https://cascais.ibercup.com/en/matches/team/cat/1703">Le&#227;o Altivo</a>. We had 77% possession, 10 shots on goal, but we just couldn&#8217;t finish. My kid made a really nice shot that the goalkeeper managed to touch and it hit the post. That was the most dangerous threat we had in the game, but unfortunately, no goal!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qi-T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qi-T!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png 424w, https://substackcdn.com/image/fetch/$s_!qi-T!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png 848w, https://substackcdn.com/image/fetch/$s_!qi-T!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png 1272w, https://substackcdn.com/image/fetch/$s_!qi-T!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qi-T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png" width="800" height="322" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7685f488-12c4-4cad-be64-345445aa2bba_800x322.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:322,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qi-T!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png 424w, https://substackcdn.com/image/fetch/$s_!qi-T!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png 848w, https://substackcdn.com/image/fetch/$s_!qi-T!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png 1272w, https://substackcdn.com/image/fetch/$s_!qi-T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7685f488-12c4-4cad-be64-345445aa2bba_800x322.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://cascais.ibercup.com/en/matches/team/cat/1703">Le&#227;o Altivo</a> vs <a href="https://cascais.ibercup.com/en/matches/team/cat/1652">Washington Epd</a></figcaption></figure></div><p><em><strong>April 6th at 11 am </strong></em>&#128172;<em><strong>: </strong>Here I am now, in between soccer games, updating the code based on replit. I was able to use the OpenAI library, which is nice. I was also able to call the API directly via Axios. Both approaches though, I was getting back a 429 (Too many requests) from OpenAI.</em></p><p><em><strong>April 6th at noon </strong></em>&#9917;<em><strong>: </strong>The soccer team won 7&#8211;0. </em>My kid earned a penalty then finished it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nk2_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nk2_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png 424w, https://substackcdn.com/image/fetch/$s_!nk2_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png 848w, https://substackcdn.com/image/fetch/$s_!nk2_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png 1272w, https://substackcdn.com/image/fetch/$s_!nk2_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nk2_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png" width="800" height="321" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:321,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nk2_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png 424w, https://substackcdn.com/image/fetch/$s_!nk2_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png 848w, https://substackcdn.com/image/fetch/$s_!nk2_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png 1272w, https://substackcdn.com/image/fetch/$s_!nk2_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c703815-94a5-4ea6-9c0d-f6a22e38bd21_800x321.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://cascais.ibercup.com/en/matches/team/cat/1652">Washington Epd</a> vs <a href="https://cascais.ibercup.com/en/matches/team/cat/1711">SL Olivais</a></figcaption></figure></div><p><em><strong>April 6th at 5:50 pm </strong></em>&#9917;<em><strong>: </strong>another win 8&#8211;1.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bmt3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bmt3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png 424w, https://substackcdn.com/image/fetch/$s_!Bmt3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png 848w, https://substackcdn.com/image/fetch/$s_!Bmt3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png 1272w, https://substackcdn.com/image/fetch/$s_!Bmt3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bmt3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png" width="800" height="303" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:303,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Bmt3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png 424w, https://substackcdn.com/image/fetch/$s_!Bmt3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png 848w, https://substackcdn.com/image/fetch/$s_!Bmt3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png 1272w, https://substackcdn.com/image/fetch/$s_!Bmt3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff42c1c4-b15e-42ee-8b87-727637fb1975_800x303.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://cascais.ibercup.com/en/matches/team/cat/1566">GS Carcavelos A</a> vs <a href="https://cascais.ibercup.com/en/matches/team/cat/1652">Washington Epd</a></figcaption></figure></div><p><em><strong>April 7th at 10:50 am </strong></em>&#9917;<em>: we lost 1&#8211;5 at the playoffs to a really good team, </em><a href="https://cascais.ibercup.com/en/matches/team/cat/1642">FC Shakhtar Donetsk</a><em>. First half, our team was surprised by the level of play and speed of the opposing team. They were clearly at a much higher level than the other 4 teams we&#8217;ve played with. First half, they&#8217;ve scored 4 goals. Second half, we&#8217;ve adjusted to their style of play and got a goal each.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zCDy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zCDy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png 424w, https://substackcdn.com/image/fetch/$s_!zCDy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png 848w, https://substackcdn.com/image/fetch/$s_!zCDy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png 1272w, https://substackcdn.com/image/fetch/$s_!zCDy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zCDy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png" width="800" height="297" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:297,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!zCDy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png 424w, https://substackcdn.com/image/fetch/$s_!zCDy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png 848w, https://substackcdn.com/image/fetch/$s_!zCDy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png 1272w, https://substackcdn.com/image/fetch/$s_!zCDy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F524b75d9-a45f-49aa-8689-5109adb710eb_800x297.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://cascais.ibercup.com/en/matches/team/cat/1642">FC Shakhtar Donetsk</a> vs <a href="https://cascais.ibercup.com/en/matches/team/cat/1652">Washington Epd</a></figcaption></figure></div><p><em><strong>April 7th at 4:30 pm </strong></em>&#128084;<em>: 1.5 hours of work meetings and about ~0.5 hour of work.</em></p><h4>Showing User Notifications</h4><p><em><strong>April 7th at midnight </strong></em>&#128172;<em><strong>:</strong></em> <em>The OpenAI errors seemed like something I cannot control, so I have decided to route my energy into surfacing errors and successes directly in different parts of the UI.</em></p><p>When a failure happens, I&#8217;ll see a notification message in the UI when there is an error. ChatGPT helped me generate all the code and allowed me to surface the notification from any child React component.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8H5n!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8H5n!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png 424w, https://substackcdn.com/image/fetch/$s_!8H5n!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png 848w, https://substackcdn.com/image/fetch/$s_!8H5n!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png 1272w, https://substackcdn.com/image/fetch/$s_!8H5n!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8H5n!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png" width="800" height="479" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/82630223-bcf5-4472-bf81-00e6861242bd_800x479.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:479,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8H5n!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png 424w, https://substackcdn.com/image/fetch/$s_!8H5n!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png 848w, https://substackcdn.com/image/fetch/$s_!8H5n!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png 1272w, https://substackcdn.com/image/fetch/$s_!8H5n!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82630223-bcf5-4472-bf81-00e6861242bd_800x479.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Sample Error notification calling the GPT API</figcaption></figure></div><p>I&#8217;ll also continue to improve the look &amp; feel of the notification UI and leverage it in other places in the web app. For example, when the request for a new exercise is completed successfully.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ofQg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ofQg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png 424w, https://substackcdn.com/image/fetch/$s_!ofQg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png 848w, https://substackcdn.com/image/fetch/$s_!ofQg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png 1272w, https://substackcdn.com/image/fetch/$s_!ofQg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ofQg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png" width="694" height="302" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:302,&quot;width&quot;:694,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ofQg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png 424w, https://substackcdn.com/image/fetch/$s_!ofQg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png 848w, https://substackcdn.com/image/fetch/$s_!ofQg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png 1272w, https://substackcdn.com/image/fetch/$s_!ofQg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd52a9af1-7c5b-4828-85c3-f2f6311b547b_694x302.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Sample success notification</figcaption></figure></div><h4>Troubleshooting GPT API</h4><p>Back to the really important issue, why am I getting errors trying to call the GPT API? I have used other methods to make requests to the OpenAI GPT endpoint, but I am still getting the 429 response. I have decided to reach out to <a href="mailto:supporting@openai.com">supporting@openai.com</a> and see how it goes from there.</p><p><strong>April 7th at 1 am </strong>&#129782;: <em>I&#8217;ll come back and continue building this capability once I stop getting 429 rate limit errors from the GPT API.</em></p><p><em><strong>April 7th at 7 pm </strong></em>&#128172;: <em>Wait a second, although I have a ChatGPT monthly subscription, the OpenAI subscription is separate. I think I am getting the failures because I did not add billing details to my OpenAI. I am still blocked because either OpenAI or my bank is not letting me pay from Portugal (or USA VPN that is not close to my zip code).</em></p><p>It looks like my &#8220;grant&#8221; for usage expired earlier this month.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VGYN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VGYN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png 424w, https://substackcdn.com/image/fetch/$s_!VGYN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png 848w, https://substackcdn.com/image/fetch/$s_!VGYN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png 1272w, https://substackcdn.com/image/fetch/$s_!VGYN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VGYN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png" width="800" height="187" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:187,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VGYN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png 424w, https://substackcdn.com/image/fetch/$s_!VGYN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png 848w, https://substackcdn.com/image/fetch/$s_!VGYN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png 1272w, https://substackcdn.com/image/fetch/$s_!VGYN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a20d741-0df5-4293-8211-4b7c7f56faf5_800x187.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>I found a way to pay by adding another card. It took a few minutes, and now it is working, based on testing in <a href="https://platform.openai.com/playground/">OpenAI Playground</a>!</p><h4>The GPT Experience</h4><p>When the user types an exercise in the &#8220;Exercise Name&#8221; field, a &#8220;Generate&#8221; button will show up.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nPzz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nPzz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png 424w, https://substackcdn.com/image/fetch/$s_!nPzz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png 848w, https://substackcdn.com/image/fetch/$s_!nPzz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png 1272w, https://substackcdn.com/image/fetch/$s_!nPzz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nPzz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png" width="800" height="580" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:580,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nPzz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png 424w, https://substackcdn.com/image/fetch/$s_!nPzz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png 848w, https://substackcdn.com/image/fetch/$s_!nPzz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png 1272w, https://substackcdn.com/image/fetch/$s_!nPzz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bc13ec2-2345-4e81-8361-0d5b06d78b22_800x580.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Generate all exercise data via GPT based on exercise name</figcaption></figure></div><p>When the user clicks on the &#8220;Generate&#8221; button, a request (prompt) is made to GPT-4 to get the following fields:</p><ul><li><p><strong>Category: </strong>Identify a category for the exercise &#8220;${exerciseName}&#8221;. The response has to be a number between 1 and 5, where Warmup is 1, Progression is 2, Inversion is 3, Strengthen is 4, and Meditation is 5</p></li><li><p><strong>SubCategory: </strong>Identify a subcategory for the exercise &#8220;${exerciseName}&#8221;. The response should be a string no longer than 20 characters.</p></li><li><p><strong>Instructions: </strong>Fetch the How To instructions for the exercise &#8220;${exerciseName}&#8221;. The response should be a string between 200 and 500 characters.</p></li><li><p><strong>Intensity: </strong>Identify the intensity level of the exercise &#8220;${exerciseName}&#8221;. The response has to be a number between 1 and 15, where 1 is easiest and 15 is hardest.</p></li><li><p><strong>Tips: </strong>Generate in JSON format 3 tips for exercise &#8220;${exerciseName}&#8221; in the format [{ title, body }]</p></li></ul><p>I make the requests sequentially to GPT-4 (because in parallel, I got back HTTP 400's). As each request is made, a loading indicator is shown next to each field. For example, below is a screenshot of the &#8220;How To Instructions&#8221; being fetched (not showing very clearly in screenshot since it is animated).</p><p>I made the requests to GPT-4 sequentially because when I tried to do them in parallel, I received HTTP 400 errors. As each request is made, a loading indicator appears next to the corresponding field. For instance, the screenshot below displays the fetching of the &#8220;How To Instructions&#8221; (not very clear in the screenshot since it&#8217;s an animation).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!T9N5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!T9N5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png 424w, https://substackcdn.com/image/fetch/$s_!T9N5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png 848w, https://substackcdn.com/image/fetch/$s_!T9N5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png 1272w, https://substackcdn.com/image/fetch/$s_!T9N5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!T9N5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png" width="800" height="577" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:577,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!T9N5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png 424w, https://substackcdn.com/image/fetch/$s_!T9N5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png 848w, https://substackcdn.com/image/fetch/$s_!T9N5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png 1272w, https://substackcdn.com/image/fetch/$s_!T9N5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fea3896-26b5-4dd5-9e56-16e19d337b94_800x577.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Loading Indicator per Field being fetched by GPT API</figcaption></figure></div><p>Then the Tips tab is automatically clicked, a loading indicator is shown until 3 tips are fetched from GPT.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZUxJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png 424w, https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png 848w, https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png 1272w, https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png" width="800" height="935" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/caacf90f-b923-4960-a791-f53f2fea43c0_800x935.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:935,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png 424w, https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png 848w, https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png 1272w, https://substackcdn.com/image/fetch/$s_!ZUxJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcaacf90f-b923-4960-a791-f53f2fea43c0_800x935.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!w6zX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!w6zX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png 424w, https://substackcdn.com/image/fetch/$s_!w6zX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png 848w, https://substackcdn.com/image/fetch/$s_!w6zX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png 1272w, https://substackcdn.com/image/fetch/$s_!w6zX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!w6zX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png" width="600" height="858" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:858,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!w6zX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png 424w, https://substackcdn.com/image/fetch/$s_!w6zX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png 848w, https://substackcdn.com/image/fetch/$s_!w6zX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png 1272w, https://substackcdn.com/image/fetch/$s_!w6zX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e7f8568-40fe-45e5-810f-ba12d4ad83af_600x858.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Loading Tips via GPT</figcaption></figure></div><p>All of this was working great locally, until I pushed the code to production. Given that it takes a little time to talk to GPT-4 to fetch things like an exercise &#8220;How To&#8221; description, it was timing out in production with error code HTTP 504! And as it turns out, Vercel only lets you change the timeout when you upgrade your plan! For that reason, I&#8217;ve decided to move from model &#8220;gpt-4&#8221; to model &#8220;gpt-3.5-turbo&#8221;.</p><p>Since GPT-3 is faster, the request to the API finished before Vercel timed out the request.</p><div><hr></div><h3>Mobile Responsiveness</h3><p>I&#8217;ve tested the experience on my iPhone and I&#8217;m happy with the experience.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!suQy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!suQy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!suQy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!suQy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!suQy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!suQy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png" width="400" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!suQy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!suQy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!suQy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!suQy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a320589-5e58-445e-b043-1afa6b6bcde0_400x867.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PTfX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PTfX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!PTfX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!PTfX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!PTfX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PTfX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png" width="400" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PTfX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!PTfX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!PTfX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!PTfX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ca77e8-01ea-4aa4-842d-d0af8d8a1438_400x867.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OWU6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OWU6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!OWU6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!OWU6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!OWU6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OWU6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png" width="400" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OWU6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png 424w, https://substackcdn.com/image/fetch/$s_!OWU6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png 848w, https://substackcdn.com/image/fetch/$s_!OWU6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png 1272w, https://substackcdn.com/image/fetch/$s_!OWU6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec02001b-b96a-4a4a-8dd1-85706377e825_400x867.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Entry Point, About Form, Tips Form</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!b45Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!b45Z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!b45Z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!b45Z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!b45Z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!b45Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png" width="600" height="1301" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1301,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!b45Z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!b45Z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!b45Z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!b45Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e95be9-981d-426b-baf8-4dd5bcd94274_600x1301.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aMfT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aMfT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!aMfT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!aMfT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!aMfT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aMfT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png" width="600" height="1301" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1301,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!aMfT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!aMfT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!aMfT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!aMfT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2be4ed-a4b7-471a-ab00-1f269abc887b_600x1301.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image Selector, YouTube Video Selector</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IZkO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IZkO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!IZkO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!IZkO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!IZkO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IZkO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png" width="600" height="1301" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1301,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IZkO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!IZkO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!IZkO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!IZkO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf71d6bd-3263-49e7-b965-d761efc77d80_600x1301.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pUSY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pUSY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!pUSY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!pUSY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!pUSY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pUSY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png" width="600" height="1301" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1301,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pUSY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png 424w, https://substackcdn.com/image/fetch/$s_!pUSY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png 848w, https://substackcdn.com/image/fetch/$s_!pUSY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png 1272w, https://substackcdn.com/image/fetch/$s_!pUSY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feafda708-2f86-4c6b-8bf8-17f4c39cc312_600x1301.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Info, Success and Error Messages</figcaption></figure></div><div><hr></div><h3>Generating Image Data</h3><p>At some point, I&#8217;d like to be able to use the DALL-E API to generate an svg exercise figure based on the selected image in the exercise request.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lGVs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lGVs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png 424w, https://substackcdn.com/image/fetch/$s_!lGVs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png 848w, https://substackcdn.com/image/fetch/$s_!lGVs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png 1272w, https://substackcdn.com/image/fetch/$s_!lGVs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lGVs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png" width="425" height="425" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:425,&quot;width&quot;:425,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lGVs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png 424w, https://substackcdn.com/image/fetch/$s_!lGVs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png 848w, https://substackcdn.com/image/fetch/$s_!lGVs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png 1272w, https://substackcdn.com/image/fetch/$s_!lGVs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b484495-dae3-468a-8f32-e87f2af6bda3_425x425.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!h4uH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!h4uH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png 424w, https://substackcdn.com/image/fetch/$s_!h4uH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png 848w, https://substackcdn.com/image/fetch/$s_!h4uH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png 1272w, https://substackcdn.com/image/fetch/$s_!h4uH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!h4uH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png" width="150" height="150" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:150,&quot;width&quot;:150,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!h4uH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png 424w, https://substackcdn.com/image/fetch/$s_!h4uH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png 848w, https://substackcdn.com/image/fetch/$s_!h4uH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png 1272w, https://substackcdn.com/image/fetch/$s_!h4uH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e19cb8-836e-4bf2-b3e7-4d769794de1a_150x150.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Input and Output</figcaption></figure></div><p>This way, newly introduced exercises to the catalog require minimal effort to fit into the look &amp; feel of the exercise library.</p><div><hr></div><h3>Conclusion</h3><p>ChatGPT has significantly boosted my coding effectiveness, helping me save valuable time. By integrating it into the NextJS + React exercise catalog app development process, I was able to generate code and implement user interface enhancements such as the exercise suggestion mechanism quickly.</p><p>While ChatGPT was an essential asset in the development process, developers must balance their reliance on AI-generated code with their critical thinking skills. Over-reliance on AI-generated code can lead to reduced understanding of the implemented code and unintended complexity.</p><p>I invite you to share your stories, give feedback, or suggest additional features you would like to see in the app. As demonstrated by the exercise catalog app, embracing AI-assisted development tools can lead to impressive results and foster continuous learning. Let&#8217;s use these tools responsibly and thoughtfully to enhance our productivity and skills in the ever-evolving world of software development.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The Missing Dev Guide for Firebase and MailChimp Integration]]></title><description><![CDATA[Moved from Medium. Original Post Date: August 27th 2022.]]></description><link>https://www.ali-b.com/p/the-missing-dev-guide-for-firebase</link><guid isPermaLink="false">https://www.ali-b.com/p/the-missing-dev-guide-for-firebase</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:42:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Bihm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There is a <a href="https://firebase.google.com/products/extensions/mailchimp-mailchimp-firebase-sync">Firebase extension</a> available to create and update MailChimp contact data based on your Firebase Authentication and Firestore documents. The extension has some documentation, but it&#8217;s hard to follow the steps to configure it properly and troubleshoot issues that arise.</p><h3>Configuring the extension</h3><p>The extension leverages the following Firebase products:</p><ul><li><p><a href="https://firebase.google.com/docs/auth">Authentication</a> to manage (add/remove) users</p></li><li><p><a href="https://firebase.google.com/docs/firestore">Cloud Firestore</a> to create member tags, merge fields, and member events with Mailchimp.</p></li></ul><p>Let&#8217;s focus first on the &#8220;required&#8221; fields to be configured in the extension. Luckily, those are pretty easy to configure and the extension has all the details for you to find those values.</p><ul><li><p><strong>Cloud Functions location</strong>: Where do you want to deploy the functions created for this extension?</p></li><li><p><strong>Mailchimp OAuth Token</strong>: To obtain a Mailchimp OAuth Token, <a href="https://firebase.mailchimp.com/index.html">click here</a>.</p></li><li><p><strong>Audience ID</strong>: What is the Mailchimp Audience ID to which you want to subscribe new users? To find your Audience ID: visit <a href="https://admin.mailchimp.com/lists">https://admin.mailchimp.com/lists</a>, click on the desired audience or create a new audience, then select Settings. Look for Audience ID (for example, <em>27735fc60a</em>).</p></li><li><p><strong>Contact status</strong>: When the extension adds a new user to the Mailchimp audience, what is their initial status? This value can be <em>subscribed</em> or <em>pending</em>. <em>Subscribed</em> means the user can receive campaigns; <em>pending</em> means the user still needs to opt-in to receive campaigns.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bihm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bihm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png 424w, https://substackcdn.com/image/fetch/$s_!Bihm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png 848w, https://substackcdn.com/image/fetch/$s_!Bihm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png 1272w, https://substackcdn.com/image/fetch/$s_!Bihm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bihm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png" width="800" height="657" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:657,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Bihm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png 424w, https://substackcdn.com/image/fetch/$s_!Bihm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png 848w, https://substackcdn.com/image/fetch/$s_!Bihm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png 1272w, https://substackcdn.com/image/fetch/$s_!Bihm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79a2be30-6627-4b73-b6e4-2eefec76fb13_800x657.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Required Configs in MailChimp Firebase Extension</figcaption></figure></div><p>Do not worry yet about configuring the rest of the extension settings. For the Firestore Cloud based capabilities, you can leave them as &#8220;unused&#8221;. This way, you can focus on verifying that &#8220;adding/removing users&#8221; works first, then add those more advanced capabilities later.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LT6M!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LT6M!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png 424w, https://substackcdn.com/image/fetch/$s_!LT6M!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png 848w, https://substackcdn.com/image/fetch/$s_!LT6M!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png 1272w, https://substackcdn.com/image/fetch/$s_!LT6M!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LT6M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png" width="423" height="589" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:589,&quot;width&quot;:423,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LT6M!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png 424w, https://substackcdn.com/image/fetch/$s_!LT6M!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png 848w, https://substackcdn.com/image/fetch/$s_!LT6M!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png 1272w, https://substackcdn.com/image/fetch/$s_!LT6M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2638edcb-2b00-4f9d-8161-d1f1bdd9c6aa_423x589.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Advanced Configs in MailChimp Firebase Extension that can be left unused for now</figcaption></figure></div><p><strong>NOTE</strong>: Always use &#8220;subscribed&#8221; rather than &#8220;pending&#8221; if you want the integration to just work. Read more if you want to learn why.</p><p>Once the extension is installed, it creates 5 Firebase functions: 2 that are authentication-based and 3 that are Firestore-based.</p><ol><li><p><strong>Authentication</strong>: (1) Create User, (2) Delete User</p></li><li><p><strong>Cloud Firestore</strong>: (3) Create member tags, (4) merge fields, and (5) member events</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FSQ3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FSQ3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png 424w, https://substackcdn.com/image/fetch/$s_!FSQ3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png 848w, https://substackcdn.com/image/fetch/$s_!FSQ3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png 1272w, https://substackcdn.com/image/fetch/$s_!FSQ3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FSQ3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png" width="462" height="320" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:320,&quot;width&quot;:462,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FSQ3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png 424w, https://substackcdn.com/image/fetch/$s_!FSQ3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png 848w, https://substackcdn.com/image/fetch/$s_!FSQ3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png 1272w, https://substackcdn.com/image/fetch/$s_!FSQ3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa76dbc13-a913-4b18-8d0c-55909f0310d2_462x320.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Firebase functions created when extension is installed</figcaption></figure></div><h3>Authentication Based Capabilities</h3><p>Assuming you already use Firebase Authentication for new users that sign up to your web or mobile app, you could leverage the extension to add/remove those users in MailChimp. In other words, keep your list of users in MailChimp in sync with the one in Firebase Authentication.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qN5b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qN5b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png 424w, https://substackcdn.com/image/fetch/$s_!qN5b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png 848w, https://substackcdn.com/image/fetch/$s_!qN5b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png 1272w, https://substackcdn.com/image/fetch/$s_!qN5b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qN5b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png" width="800" height="344" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:344,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qN5b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png 424w, https://substackcdn.com/image/fetch/$s_!qN5b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png 848w, https://substackcdn.com/image/fetch/$s_!qN5b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png 1272w, https://substackcdn.com/image/fetch/$s_!qN5b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f30806e-64aa-46b6-8e60-988e3d06ec51_800x344.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Firebase Authentication</figcaption></figure></div><h3>Adding Users to MailChimp</h3><p>As mentioned earlier, when the extension is installed, it creates a Firebase Cloud function that listens for new user accounts (as managed by Firebase Authentication), and then automatically adds the new user to your specified MailChimp audience.</p><p>My first issue was managing to get a new user that signs up via Firebase Authentication to be created in MailChimp. I had the basic configs for <a href="http://firebase.mailchimp.com/index.html">Auth token</a> and <a href="https://admin.mailchimp.com/lists">Audience Id</a>, but for whatever reason, I couldn&#8217;t see the new contact being created in MailChimp.</p><h3>Basic Testing for Adding User To MailChimp</h3><p>In Firebase Authentication, click &#8220;Add User&#8221; to add a new user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!keAv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!keAv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png 424w, https://substackcdn.com/image/fetch/$s_!keAv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png 848w, https://substackcdn.com/image/fetch/$s_!keAv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png 1272w, https://substackcdn.com/image/fetch/$s_!keAv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!keAv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png" width="800" height="322" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dccd0f64-807f-439a-b0d7-c05332f03220_800x322.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:322,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!keAv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png 424w, https://substackcdn.com/image/fetch/$s_!keAv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png 848w, https://substackcdn.com/image/fetch/$s_!keAv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png 1272w, https://substackcdn.com/image/fetch/$s_!keAv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdccd0f64-807f-439a-b0d7-c05332f03220_800x322.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Adding a User Manually in Firebase Authentication</figcaption></figure></div><p>This creates this user with the following ID in Firebase Auth.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1r7f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1r7f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png 424w, https://substackcdn.com/image/fetch/$s_!1r7f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png 848w, https://substackcdn.com/image/fetch/$s_!1r7f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png 1272w, https://substackcdn.com/image/fetch/$s_!1r7f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1r7f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png" width="800" height="70" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:70,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1r7f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png 424w, https://substackcdn.com/image/fetch/$s_!1r7f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png 848w, https://substackcdn.com/image/fetch/$s_!1r7f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png 1272w, https://substackcdn.com/image/fetch/$s_!1r7f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2580e4e-4968-4e0b-a93f-8a15d915cdc3_800x70.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Added User in Firebase Authentication</figcaption></figure></div><p>In theory, I should be able to just go to MailChimp and see the newly created user. So I went to my MailChimp account at <a href="https://admin.mailchimp.com/lists/">https://admin.mailchimp.com/lists/</a>, clicked on the audience I connected earlier in the config, and found nothing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LpI9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LpI9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png 424w, https://substackcdn.com/image/fetch/$s_!LpI9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png 848w, https://substackcdn.com/image/fetch/$s_!LpI9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png 1272w, https://substackcdn.com/image/fetch/$s_!LpI9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LpI9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png" width="682" height="459" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:459,&quot;width&quot;:682,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LpI9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png 424w, https://substackcdn.com/image/fetch/$s_!LpI9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png 848w, https://substackcdn.com/image/fetch/$s_!LpI9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png 1272w, https://substackcdn.com/image/fetch/$s_!LpI9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2e6380-211e-40e7-95c4-06abc77c680a_682x459.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Member Not Found in MailChimp</figcaption></figure></div><h3>Troubleshooting</h3><p>So why isn&#8217;t the user getting created in MailChimp?</p><p>I first went to the &#8220;user.create&#8221; Firebase function and opened the logs.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iJmN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iJmN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png 424w, https://substackcdn.com/image/fetch/$s_!iJmN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png 848w, https://substackcdn.com/image/fetch/$s_!iJmN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png 1272w, https://substackcdn.com/image/fetch/$s_!iJmN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iJmN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png" width="800" height="150" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:150,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iJmN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png 424w, https://substackcdn.com/image/fetch/$s_!iJmN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png 848w, https://substackcdn.com/image/fetch/$s_!iJmN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png 1272w, https://substackcdn.com/image/fetch/$s_!iJmN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe61da930-98b5-4d1b-ad98-7dbbef6d96de_800x150.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Firebase Function Logs Entry Point</figcaption></figure></div><p>In the logs, it looked like everything was working as expected.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dLxc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dLxc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png 424w, https://substackcdn.com/image/fetch/$s_!dLxc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png 848w, https://substackcdn.com/image/fetch/$s_!dLxc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png 1272w, https://substackcdn.com/image/fetch/$s_!dLxc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dLxc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png" width="800" height="225" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:225,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dLxc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png 424w, https://substackcdn.com/image/fetch/$s_!dLxc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png 848w, https://substackcdn.com/image/fetch/$s_!dLxc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png 1272w, https://substackcdn.com/image/fetch/$s_!dLxc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F543d5015-0bdf-4865-8286-5f83cfb2d680_800x225.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Showing Success in Firebase Function Logs</figcaption></figure></div><p>It&#8217;s attempting to create in MailChimp the same user I added in Firebase Auth (same ID), and it&#8217;s showing that the addition was completed successfully.</p><p><strong>Firebase ID</strong>: 9JjCwv9O2jPpELIN70KUsWmqpRr1</p><p><strong>MailChimp ID</strong>: f8f1a4191871855a1d716485fac46eea</p><p>Yet, I do not see the user in MailChimp!</p><p>Looking at the <a href="https://github.com/mailchimp/Firebase/blob/master/functions/index.js">source code</a> of the function, it was basically making a POST call to /lists/&lt;mailchimp_audienceId&gt;/member passing to it <em>email_address</em> and <em>status</em>, but for whatever reason, the user was not visible in MailChimp.</p><pre><code>exports.addUserToList = functions.handler.auth.user.onCreate(
  async (user) =&gt; {
    logs.start();</code></pre><pre><code>if (!mailchimp) {
      logs.mailchimpNotInitialized();
      return;
    }</code></pre><pre><code>const { email, uid } = user;
    if (!email) {
      logs.userNoEmail();
      return;
    }</code></pre><pre><code>try {
      logs.userAdding(uid, config.mailchimpAudienceId);
      const results = await mailchimp.post(
        `/lists/${config.mailchimpAudienceId}/members`,
        {
          email_address: email,
          status: config.mailchimpContactStatus,
        }
      );
      logs.userAdded(
        uid,
        config.mailchimpAudienceId,
        results.id,
        config.mailchimpContactStatus
      );
      logs.complete();
    } catch (err) {
      err.title === 'Member Exists' ? logs.userAlreadyInAudience( ) : logs.errorAddUser(err);
    }
  }
);</code></pre><p>I then decided to check out the <a href="https://mailchimp.com/developer/marketing/api/list-members/">MailChimp API</a> to see if the user is actually being created in MailChimp and maybe I&#8217;m not figuring where to go in the UI to find it.</p><p>Given that I already have the MailChimp user id from the logs, I decided to try and fetch it through the MailChimp API:</p><p>https://&lt;<em>dc</em>&gt;.api.mailchimp.com/3.0/lists/&lt;<em>mailchimp_audienceId</em>&gt;/members/&lt;member_id&gt;</p><p>To be able to make API calls, you need to create an <a href="https://mailchimp.com/help/about-api-keys/">API key</a>. The &lt;<em>dc</em>&gt; for me was <em>us19</em>, this value can be pulled from the end of the API key.</p><p>In <a href="https://www.postman.com/">PostMan</a>, I created the GET request, and there it was, the user is in the system!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0hhW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0hhW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png 424w, https://substackcdn.com/image/fetch/$s_!0hhW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png 848w, https://substackcdn.com/image/fetch/$s_!0hhW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png 1272w, https://substackcdn.com/image/fetch/$s_!0hhW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0hhW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png" width="800" height="445" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:445,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0hhW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png 424w, https://substackcdn.com/image/fetch/$s_!0hhW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png 848w, https://substackcdn.com/image/fetch/$s_!0hhW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png 1272w, https://substackcdn.com/image/fetch/$s_!0hhW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26e9d73c-0972-4e6f-a769-5ba10ffe91d8_800x445.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">GET Request in PostMan to retrieve a specific MailChimp member</figcaption></figure></div><p>It finally hit me. &#8220;Pending&#8221; status might be the problem. I went to <a href="https://mailchimp.com/help/about-your-contacts/">MailChimp online documentation</a> and learned this:</p><p><em>A pending contact is someone who has completed a signup form but has not confirmed their opt-in. The contact&#8217;s email address won&#8217;t be added to your audience until they confirm their opt-in, and you won&#8217;t be able to view them in your audience. After 60 days, if they have not confirmed their opt-in, the contact&#8217;s email address and any other information they provided will be removed and deleted.</em></p><p>I also saw this in my email. When I confirmed, the status moved from &#8220;pending&#8221; to &#8220;subscribed&#8221;, and then I was able to find this user in the MailChimp audience.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wvk1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wvk1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png 424w, https://substackcdn.com/image/fetch/$s_!Wvk1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png 848w, https://substackcdn.com/image/fetch/$s_!Wvk1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png 1272w, https://substackcdn.com/image/fetch/$s_!Wvk1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wvk1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png" width="723" height="644" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:644,&quot;width&quot;:723,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Wvk1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png 424w, https://substackcdn.com/image/fetch/$s_!Wvk1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png 848w, https://substackcdn.com/image/fetch/$s_!Wvk1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png 1272w, https://substackcdn.com/image/fetch/$s_!Wvk1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76b1f52-b0f9-410a-ac92-ce77d03093b1_723x644.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">MailChimp Email to Confirm Subscription</figcaption></figure></div><p>I couldn&#8217;t find where this form could be configured (might relate to my Squarespace and MailChimp integration), and I also realized this might not be the best experience to welcome new users with a subscribe message. As a result, I opted to create new users in MailChimp with the &#8220;subscribed&#8221; status, so I can focus on building the right &#8220;Welcome&#8221; message for new users that sign up through my app.</p><p>Another thing to keep an eye on is using &#8220;valid&#8221; email addresses when testing. For example, I tried adding a user &#8220;<a href="mailto:mailchimptest@test.com">mailchimptest@test.com</a>&#8221;, but the user did not end up being added to MailChimp since it was considered as looking &#8220;fake&#8221; or &#8220;invalid&#8221;.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dbnP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dbnP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png 424w, https://substackcdn.com/image/fetch/$s_!dbnP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png 848w, https://substackcdn.com/image/fetch/$s_!dbnP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png 1272w, https://substackcdn.com/image/fetch/$s_!dbnP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dbnP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png" width="800" height="230" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:230,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dbnP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png 424w, https://substackcdn.com/image/fetch/$s_!dbnP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png 848w, https://substackcdn.com/image/fetch/$s_!dbnP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png 1272w, https://substackcdn.com/image/fetch/$s_!dbnP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F979e34a6-a20c-4047-8ec2-06bacbfa34ee_800x230.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Error in the Logs for using Invalid Email Addresses</figcaption></figure></div><h3>Deleting Users in MailChimp</h3><p>For GDPR compliance, the extension also creates a Cloud Function that listens for existing user accounts to be deleted (as managed by Firebase Authentication), and then automatically removes them from your specified MailChimp audience.</p><h3>Cloud Firestore Based Capabilities</h3><p>The capabilities dependent on Cloud firestore have two things to configure:</p><ol><li><p><strong>Watch Path</strong>: the name or path of the Firebase collection to lookup data.</p></li><li><p><strong>Config</strong>: the JSON mapping that will tell the extension what data to look for in the document to pass it to MailChimp</p></li></ol><p>Each of those capabilities will get one Firebase Cloud function created, to listen to document changes in the specified Firestore collection and map the data based on the config defined in the extension into MailChimp.</p><ol><li><p><strong>Merge fields Cloud Function</strong> provides the ability to create new properties that can be associated with Mailchimp subscriber. The <em>mergeFieldsHandler</em> function listens for Firestore write events based on specified config path, then automatically populates the Mailchimp subscriber&#8217;s respective merge fields. In other words, all this does is get additional data about the user and map it into member (contact) fields in MailChimp.</p></li><li><p><strong>Member Tags Cloud Function</strong> provides the ability to associate &#8220;metadata&#8221; or &#8220;labels&#8221; with a Mailchimp subscriber. The <em>memberTagsHandler</em> function listens for Firestore write events based on specified config path, then automatically classifies the document data as Mailchimp subscriber <strong>tags</strong>. So all this does is create tags in MailChimp and associate them with users (members).</p></li><li><p><strong>Member events Cloud Function</strong> creates Mailchimp specific activity events that can be created and associated with a predefined action. The <em>memberEventsHandler</em> function listens for Firestore write events based on specified config path, then automatically uses the document data to create a Mailchimp event on the subscriber&#8217;s profile which can subsequently trigger automation workflows.</p></li></ol><h3>Updating User Data in MailChimp</h3><p>This is a mechanism to pull in additional information about the user from a document in Firebase and funnel it as user properties for the contact (member) in MailChimp.</p><p>The two settings to configure:</p><ul><li><p><strong>Firebase Merge Fields Watch Path</strong>: The Firestore collection to watch for merge field changes</p></li><li><p><strong>Firebase Merge Fields Config</strong>: Provide a configuration mapping in JSON format indicating which Firestore properties to listen for and associate as Mailchimp merge fields.</p></li></ul><h3>Firebase Merge Fields Config</h3><p>The JSON format is simple, It has two required fields that need to be set:</p><ul><li><p><strong>subscriberEmail</strong>&#8202;&#8212;&#8202;The Firestore document field capturing the user email as is recognized by Mailchimp. This is how MailChimp will know which member to update with the new field data.</p></li><li><p><strong>mergeFields</strong>&#8202;&#8212;&#8202;JSON mapping representing the Firestore document fields to associate with Mailchimp Merge Fields. Basically, what properties to take from the Firestore document and update in the MailChimp member.</p></li></ul><p>Here is an example of what this configuration would look like in JSON:</p><pre><code>{
  "mergeFields": {
    "firstName": "FNAME",
    "lastName": "LNAME",
    "phoneNumber": "PHONE"
  },
  "subscriberEmail": "emailAddress"
}</code></pre><p><a href="https://mailchimp.com/help/getting-started-with-merge-tags/">*|MERGE|* tags</a> are MailChimp&#8217;s way to uniquely identify a field for a member. The format of the properties inside the &#8220;mergeFields&#8221; JSON property is as follows:</p><ul><li><p>&#8220;Firestore property name&#8221;: &#8220;MERGE field ID&#8221;</p></li></ul><p>You can view and modify the Merge tags in MailChimp.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!akKy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!akKy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png 424w, https://substackcdn.com/image/fetch/$s_!akKy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png 848w, https://substackcdn.com/image/fetch/$s_!akKy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png 1272w, https://substackcdn.com/image/fetch/$s_!akKy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!akKy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png" width="800" height="342" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:342,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!akKy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png 424w, https://substackcdn.com/image/fetch/$s_!akKy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png 848w, https://substackcdn.com/image/fetch/$s_!akKy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png 1272w, https://substackcdn.com/image/fetch/$s_!akKy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd0883e7-f1e9-421b-8fa4-1198aa8f1343_800x342.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">MERGE tags (Fields) for an Audience in MailChimp</figcaption></figure></div><p>The above sample configuration assumes your Firestore collection contains documents having the following properties:</p><pre><code>{
  "firstName": "..", // The config property FNAME maps to this document field
  "lastName": "..", // The config property LNAME maps to this document field
  "phoneNumber": "..", // The config property PHONE maps to this document field
  "emailAddress": "..", // The config property "subscriberEmail" maps to this document field
}</code></pre><p>Any data associated with the mapped fields will be considered Merge Fields and the Mailchimp user&#8217;s profile will be updated accordingly.</p><p><strong>NOTE</strong>: To disable this cloud function listener, provide an empty JSON config {}.</p><h3>Example: Pass Nested Fields in your Firestore doc to MailChimp</h3><p>You can point to nested properties in the Firebase document. Here is an example:</p><pre><code>{
  "mergeFields": { 
    "userProfile.displayName": "FULLNAME", 
    "userProfile.lastActiveDate": "LASTACTIVE", 
    "userProfile.memberSince": "SINCE",
    "userMetrics.daysActive": "DAYSACTIVE",   
    "userSettings.monthlyAccessPurchased": "HASMSUB",
    "userDiagnostics.appVersion": "APPVERSION",
    "userDiagnostics.supportOnDeviceSpeechRecognition": "DEVICESR"
  },
  "subscriberEmail": "userProfile.email"
}</code></pre><p>The configuration should look like below, where &#8220;users&#8221; is the Firestore collection name and the JSON below contains the <em>subscriberEmail</em> and the field mappings between the Firestore document and the MailChimp member (<em>mergeFields</em>).</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!idqX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!idqX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png 424w, https://substackcdn.com/image/fetch/$s_!idqX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png 848w, https://substackcdn.com/image/fetch/$s_!idqX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png 1272w, https://substackcdn.com/image/fetch/$s_!idqX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!idqX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png" width="416" height="184" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:184,&quot;width&quot;:416,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!idqX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png 424w, https://substackcdn.com/image/fetch/$s_!idqX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png 848w, https://substackcdn.com/image/fetch/$s_!idqX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png 1272w, https://substackcdn.com/image/fetch/$s_!idqX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a67dc6-637d-4631-a71f-fc7ef84c9025_416x184.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Firebase MailChimp Extension config for Merge Fields</figcaption></figure></div><h3>Troubleshooting</h3><p>One of the limitations of this extension is that it only passes to MailChimp the fields that have changed within the Firestore doc. So if there are properties for an existing user (ex: Member Since = June 2020) and you enable the extension today, it won&#8217;t detect this as a changed property and will not update the MailChimp member with the value. It will always be empty in MailChimp as the extension compares changes in the Firestore doc itself rather than changes between the Firestore document and MailChimp.</p><p>See <strong>bolded</strong> code in the function definition below. Ideally, it would be nice to just pass all the &#8220;latest&#8221; values for the mapped fields in &#8220;<em>mergeFields</em>&#8221;.</p><pre><code>exports.mergeFieldsHandler = functions.handler.firestore.document
  .onWrite(async (event, context) =&gt; {
    // If an empty JSON configuration was provided then consider function as NO-OP
    if (_.isEmpty(config.mailchimpMergeField)) return null;</code></pre><pre><code>try {
      // Get the configuration settings for mailchimp merge fields as is defined in extension.yml
      const mergeFieldsConfig = config.mailchimpMergeField;</code></pre><pre><code>// Validate proper configuration settings were provided
      if (!mailchimp) {
        logs.mailchimpNotInitialized();
        return;
      }
      if (!mergeFieldsConfig.mergeFields || _.isEmpty(mergeFieldsConfig.mergeFields)) {
        functions.logger.log(`A property named 'mergeFields' is required`);
        return null;
      }
      if (!_.isObject(mergeFieldsConfig.mergeFields)) {
        functions.logger.log('Merge Fields config must be an object');
        return null;
      }</code></pre><pre><code>// Get snapshot of document before &amp; after write event
      <strong>const prevDoc = event &amp;&amp; event.before &amp;&amp; event.before.data();
      const newDoc = event &amp;&amp; event.after &amp;&amp; event.after.data();</strong></code></pre><pre><code>// Determine all the merge prior to write event
      const mergeFieldsToUpdate = Object.entries(mergeFieldsConfig.mergeFields).reduce((acc, [docFieldName, mergeFieldName]) =&gt; {
        const prevMergeFieldValue = _.get(prevDoc, docFieldName);
        // lookup the same field value in new snapshot
        const newMergeFieldValue = _.get(newDoc, docFieldName, '');
        // if delta exists, then update accumulator collection
        <strong>if (prevMergeFieldValue !== newMergeFieldValue) {
          acc[mergeFieldName] = newMergeFieldValue;
        }</strong>
        return acc;
      }, {});</code></pre><pre><code>// Compute the mailchimp subscriber email hash
      const subscriberHash = subscriberHasher(_.get(newDoc, mergeFieldsConfig.subscriberEmail));</code></pre><pre><code>const params = {
        status_if_new: config.mailchimpContactStatus,
        email_address: _.get(newDoc, mergeFieldsConfig.subscriberEmail),
        merge_fields: mergeFieldsToUpdate
      };</code></pre><pre><code>// Invoke mailchimp API with updated tags
      if (!_.isEmpty(mergeFieldsToUpdate)) {
        await mailchimp.put(`/lists/${config.mailchimpAudienceId}/members/${subscriberHash}`, params);
      }
    } catch (e) {
      functions.logger.log(e);
    }
  });</code></pre><p>I would have loved to modify this code as follows to be able to simply pass the latest values, but unfortunately, Firebase <a href="https://github.com/firebase/extensions/issues/355">does not currently support</a> extending or modifying extension code.</p><pre><code>const mergeFieldsToUpdate = Object.entries(mergeFieldsConfig.mergeFields).reduce((acc, [docFieldName, mergeFieldName]) =&gt; {
  const newMergeFieldValue = _.get(newDoc, docFieldName, '');
  acc[mergeFieldName] = newMergeFieldValue;
  return acc;
}, {});</code></pre><p>I ended up adding a <a href="https://github.com/mailchimp/Firebase/issues/43">request</a> on the MailChimp extension GitHub repo. Hopefully this gets actioned, but if it doesn&#8217;t, there is another option to manually import all the data into MailChimp. This way, you&#8217;ll have all the existing fields in MailChimp and the extension will handle changes in the future.</p><p>At a high level, here are the steps to I followed to pull my data from Firestore to BigQuery to MailChimp:</p><ul><li><p>Install the <a href="https://firebase.google.com/products/extensions/firebase-firestore-bigquery-export">Stream Collections to BigQuery</a> extension to export your Firestore collection into BigQuery</p></li><li><p>Go to <a href="https://console.cloud.google.com/bigquery">BigQuery</a> and write a SQL query to pull the data you need. For example:</p></li></ul><pre><code>SELECT   REPLACE(JSON_EXTRACT(data, '$.userProfile.email'), '"', '') Email,
         REPLACE(JSON_EXTRACT(data, '$.userProfile.displayName'), '"', '') FullName,
         REPLACE(JSON_EXTRACT(data, '$.userProfile.memberSince'), '"', '') AS memberSince
FROM `handstand-quest.firestore_handstand_quest.users_raw_latest`</code></pre><ul><li><p>In BigQuery, run the query and save results to CSV</p></li><li><p>Go to MailChimp and <a href="https://mailchimp.com/help/import-contacts-mailchimp/">import the CSV</a> into your Audience. It&#8217;s actually a very well built capability that lets you visually map fields between your CSV and your MailChimp member fields, then import.</p></li></ul><h3>Adding User Tags in MailChimp</h3><p>Those tags can be pushed from Firebase for the contact and then be used as <a href="https://mailchimp.com/help/getting-started-tags/">tags in MailChimp</a> to easily find contacts with specific tags.</p><p>You might wonder, what&#8217;s the point of tags if you can filter by fields. Well, you cannot filter by field values (like Excel) in MailChimp, that&#8217;s why tags will come in pretty handy.</p><p>The two settings to configure:</p><ul><li><p><strong>Firebase Member Tags Watch Path</strong>: The Firestore collection to watch for member tag changes</p></li><li><p><strong>Firebase Member Tags Config</strong>: Provide a configuration mapping in JSON format indicating which Firestore event(s) to listen for and associate as Mailchimp member tags.</p></li></ul><h3>Firebase Member Tags Config</h3><p>The JSON format is simple, It has two required fields that need to be set:</p><ul><li><p><strong>subscriberEmail</strong>&#8202;&#8212;&#8202;The Firestore document field capturing the user email as is recognized by Mailchimp. This is how MailChimp will know which member to update the tag for.</p></li><li><p><strong>memberTags</strong>&#8202;&#8212;&#8202;The Firestore document fields(s) to retrieve data from and classify as subscriber tags in Mailchimp.</p></li></ul><p>Here is an example of what this configuration would look like in JSON:</p><pre><code>{
  "memberTags": ["domainKnowledge", "jobTitle"],
  "subscriberEmail": "emailAddress"
}</code></pre><p>Assuming the Firestore document has the following fields:</p><pre><code>{
  "emailAddress": "..", // The config property 'subscriberEmail' maps to this document field
  "jobTitle": "..", // The config property 'memberTags' maps to this document field
  "domainKnowledge": "..", // The config property 'memberTags' maps to this document field
}</code></pre><p><strong>NOTE</strong>: To disable this cloud function listener, provide an empty JSON config {}.</p><h3>Example: Filter by Member Location</h3><p>Here is a screenshot of the config in the extension.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!k0-b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!k0-b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png 424w, https://substackcdn.com/image/fetch/$s_!k0-b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png 848w, https://substackcdn.com/image/fetch/$s_!k0-b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png 1272w, https://substackcdn.com/image/fetch/$s_!k0-b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!k0-b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png" width="800" height="209" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:209,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!k0-b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png 424w, https://substackcdn.com/image/fetch/$s_!k0-b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png 848w, https://substackcdn.com/image/fetch/$s_!k0-b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png 1272w, https://substackcdn.com/image/fetch/$s_!k0-b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab974918-72dd-42e2-a0cc-32ec4e1b0240_800x209.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Firebase MailChimp Extension config for Member Tags</figcaption></figure></div><p>With that up and running, I can now filter my audience in MailChimp by the different values of <em>location</em>. For example, filter all members with the tag &#8220;Seattle&#8221;.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4Qy9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4Qy9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png 424w, https://substackcdn.com/image/fetch/$s_!4Qy9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png 848w, https://substackcdn.com/image/fetch/$s_!4Qy9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png 1272w, https://substackcdn.com/image/fetch/$s_!4Qy9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4Qy9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png" width="800" height="128" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:128,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4Qy9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png 424w, https://substackcdn.com/image/fetch/$s_!4Qy9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png 848w, https://substackcdn.com/image/fetch/$s_!4Qy9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png 1272w, https://substackcdn.com/image/fetch/$s_!4Qy9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3e3067d-0057-4cef-9d56-0625decd8c07_800x128.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Members filtered by the &#8220;Seattle&#8221; location tag</figcaption></figure></div><h3>Troubleshooting</h3><p>Make sure the values in the properties that you map as <em>memberTags</em> are things you would want to group by, since the point of tags is to easily filter members who have a certain quality. For example, &#8220;<em>jobTitle</em>&#8221; makes sense as a tag since it will make it easy to filter members by Job Title. But something like &#8220;<em>firstName</em>&#8221; might not make sense.</p><p>Also, if you try to use a Bool value as a tag, based on my testing, it does not work. Ideally, the config below would result in a tag titled &#8220;<em>isCoach</em>&#8221; when the property is <em>true</em>, but neither &#8220;<em>isCoach</em>&#8221; nor &#8220;<em>true</em>&#8221;/&#8221;<em>false</em>&#8221; tags get created.</p><pre><code>{
  "memberTags": ["userProfile.isCoach"],
  "subscriberEmail": "userProfile.emailAddress"
}</code></pre><p>If resolved, this <a href="https://github.com/mailchimp/Firebase/issues/21">request</a> on the MailChimp extension Github repository could help.</p><p><strong>NOTE</strong>: Just ignore data types that are not <em>String</em>, and tags should work just fine.</p><h3>Sending Events for Automation in MailChimp</h3><p>This makes it easy to leverage MailChimp actions and automations based on events that take place in your Firebase app. For example, on a new user signup, you could send them a welcome email.</p><p>The two settings to configure:</p><ul><li><p><strong>Firebase Member Events Watch Path</strong>: The Firestore collection to watch for member event changes</p></li><li><p><strong>Firebase Member Events Config</strong>: Provide a configuration mapping in JSON format indicating which Firestore event(s) to listen for and associate as Mailchimp events.</p></li></ul><p>Before leveraging this capability, it&#8217;s important to have an understanding of how events work in MailChimp. I recommend reading MailChimp&#8217;s <a href="https://mailchimp.com/help/use-events-behavioral-targeting/">Use Events for Behavioral Targeting</a> and <a href="https://mailchimp.com/developer/marketing/guides/track-outside-activity-events/">Track Outside Activity with Events</a> to gain a perspective on all the awesome things you can do.</p><h3>Firebase Member Events Config</h3><p>The JSON format is simple, It has two required fields that need to be set:</p><ul><li><p><strong>subscriberEmail</strong>&#8202;&#8212;&#8202;The Firestore document field capturing the user email as is recognized by Mailchimp.</p></li><li><p><strong>memberEvents</strong>&#8202;&#8212;&#8202;The Firestore document fields(s) to retrieve data from and classify as member events in Mailchimp.</p></li></ul><p>Here is an example of what this configuration would look like in JSON:</p><pre><code>{
  "memberEvents": [
    "activity"
  ],
  "subscriberEmail": "emailAddress"
}</code></pre><p>Assuming the Firestore document has the following fields:</p><pre><code>{
  "emailAddress": "..", // The config property "subscriberEmail" maps to this document field
  "activity": ["send_welcome_email"] // The config property "memberEvents" maps to this document field
}</code></pre><p><strong>NOTE</strong>: To disable this cloud function listener, provide an empty JSON config {}.</p><h3>Example: Trigger Email to MailChimp</h3><p>I use the Firebase <a href="https://firebase.google.com/products/extensions/firebase-firestore-send-email">Email Trigger</a> extension to send emails based on interesting and relevant activity that happens in my app.</p><p>Given it is almost free (only cost is Firebase function running), I see myself sticking to it for email sending based on events. Clearly, there is a lot more power in leveraging MailChimp, but I&#8217;d rather stay on the MailChimp free plan (minimum paid plan is $59 per month). I&#8217;ll focus on the free capabilities of MailChimp in this section, but you should know that you would be able to do more if you have a paid MailChimp plan.</p><p>In my app, here are some of the types of events I listen to and send an email to a Google group. It helps me see on a daily basis interesting/important activities that are happening in my app.</p><ul><li><p>NewUser</p></li><li><p>Purchase</p></li><li><p>WorkoutCompleted</p></li><li><p>DailyGoalAchieved</p></li><li><p>Feedback</p></li><li><p>etc&#8230;</p></li></ul><p>This is my way to get better connected with usage in my app at a much more intimate level than metrics and Google Analytics could ever go.</p><p>With minor changes to my current process using the &#8220;Trigger Email&#8221; extension, I can route an event to MailChimp and leverage the free capability of being able to see in one place all the events that have happened relating to a specific member.</p><p>I basically write a message to the <em>messages</em> Firestore collection, and then the &#8220;Trigger Email&#8221; extension does the magic of sending the email and ensuring it gets delivered. The message basically looks like this:</p><pre><code>{
  to: '<a href="mailto:someone@example.com">someone@example.com</a>',
  message: {
    type: 'NewUser',
    subject: 'Hello from Firebase!',
    html: 'This is an &lt;code&gt;HTML&lt;/code&gt; email body.',
  }
}</code></pre><p>Here is a sample summarized email that I get at the end of each day.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bgnn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bgnn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png 424w, https://substackcdn.com/image/fetch/$s_!bgnn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png 848w, https://substackcdn.com/image/fetch/$s_!bgnn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png 1272w, https://substackcdn.com/image/fetch/$s_!bgnn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bgnn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png" width="800" height="573" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:573,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bgnn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png 424w, https://substackcdn.com/image/fetch/$s_!bgnn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png 848w, https://substackcdn.com/image/fetch/$s_!bgnn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png 1272w, https://substackcdn.com/image/fetch/$s_!bgnn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac1a3e04-17a7-4cb7-91bf-4a67820cbeb6_800x573.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Abridged Summary from Google Group, setup in &#8220;My membership settings&#8221; Subscription dropdown</figcaption></figure></div><p>I use the <a href="https://support.google.com/groups/answer/2464926?hl=en">Abridged setting</a> in Google Groups to get a single email summary in a day on my personal email that is part of the Google group, and on another email address I get every email in case I want to look at them &#8220;live&#8221; in the moment one by one.</p><p>Are are the different settings you could choose from in a Google Group:</p><ul><li><p><strong>Each email</strong>&#8202;&#8212;&#8202;Messages sent individually as they&#8217;re posted to the group.</p></li><li><p><strong>Abridged</strong>&#8202;&#8212;&#8202;Up to 25 complete messages combined into single emails and sent daily.</p></li><li><p><strong>Digest</strong>&#8202;&#8212;&#8202;Summaries of up to 150 messages combined into single emails and sent daily.</p></li><li><p><strong>No email</strong>&#8202;&#8212;&#8202;Messages from the group are not sent.</p></li></ul><p>To make it easy to connect it with the MailChimp extension, I added a new user email property that allows me to link my current event with the MailChimp extension:</p><pre><code>{
  to: '<a href="mailto:someone@example.com">someone@example.com</a>',
  message: {
    type: 'NewUser',
    user: {
      <strong>email: '<a href="mailto:user@example.com">user@example.com</a>',</strong>
      id: 'Firebase User ID'
    },
    subject: 'Hello from Firebase!',
    html: 'This is an &lt;code&gt;HTML&lt;/code&gt; email body.',
  }
}</code></pre><p>To map my Firestore document to MailChimp, I simply set this config:</p><pre><code>{
  "memberEvents": ["message.type"],
  "subscriberEmail": "message.user.email"
}</code></pre><p>Then, I simply configured the extension for events as follows:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xJsN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xJsN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png 424w, https://substackcdn.com/image/fetch/$s_!xJsN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png 848w, https://substackcdn.com/image/fetch/$s_!xJsN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png 1272w, https://substackcdn.com/image/fetch/$s_!xJsN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xJsN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png" width="800" height="358" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4535ef54-4676-4372-8402-b8c412a910b4_800x358.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:358,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xJsN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png 424w, https://substackcdn.com/image/fetch/$s_!xJsN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png 848w, https://substackcdn.com/image/fetch/$s_!xJsN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png 1272w, https://substackcdn.com/image/fetch/$s_!xJsN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4535ef54-4676-4372-8402-b8c412a910b4_800x358.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Firebase MailChimp Extension config for Member Events</figcaption></figure></div><p>Here is the goodness I got in MailChimp (activity feed in Member profile). Of course, I can build up on this capability to trigger automations, customer journeys, etc&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!71pr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!71pr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png 424w, https://substackcdn.com/image/fetch/$s_!71pr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png 848w, https://substackcdn.com/image/fetch/$s_!71pr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png 1272w, https://substackcdn.com/image/fetch/$s_!71pr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!71pr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png" width="800" height="851" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/04a4623b-7d99-440f-85a2-04533183525c_800x851.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:851,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!71pr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png 424w, https://substackcdn.com/image/fetch/$s_!71pr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png 848w, https://substackcdn.com/image/fetch/$s_!71pr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png 1272w, https://substackcdn.com/image/fetch/$s_!71pr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04a4623b-7d99-440f-85a2-04533183525c_800x851.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Member Profile in MailChimp with example events</figcaption></figure></div><p>In your case, you could link MailChimp to any collection where you&#8217;re tracking events. You could even have a custom collection that simply routes Google Analytics events with an email, then get those events linked to the member in MailChimp.</p><h3>Conclusion</h3><p>The MailChimp extension for Firebase is very powerful and simple to use, but on the surface, it&#8217;s hard to see all the goodness that could be leveraged. I hope this article with detailed step-by-step instructions will help you make the most out of it&#8230; Enjoy!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[iOS App Store Reviews — Email or Slack Notifications]]></title><description><![CDATA[Moved from Medium. Original Post: July 1st 2022.]]></description><link>https://www.ali-b.com/p/ios-app-store-reviews-email-or-slack</link><guid isPermaLink="false">https://www.ali-b.com/p/ios-app-store-reviews-email-or-slack</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:41:06 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!vahc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After having an <a href="https://www.handstandquest.com/">iOS App</a> for about 3 years on the App Store, I&#8217;ve realized I&#8217;ve been noticing app store reviews months after they are submitted, when I occasionally login to App Store Connect.</p><p>Given how valuable reviews are, it&#8217;s very important for me to instantly know as soon as someone has feedback, so I could respond and help anyway I can.</p><p>I was hoping I&#8217;d simply log in to the App Store Connect and enable the notification (at least by email), but unfortunately, nothing like this exists! I was very surprised.</p><p>So I did the usual, went to Google, and searched for exactly what I am looking for &#8220;<em>Slack notification for iOS app store review</em>&#8221;. From a quick scan, it all looked like paid solutions! No, thank you!</p><p>I started looking if Apple offers something, maybe it&#8217;s hidden somewhere, so I searched &#8220;<em>get notified for iOS app store review</em>&#8221;, &#8220;<em>ios app review api notification</em>&#8221; and more. I found this mechanism to get notified by email if a customer edits a review you&#8217;ve responded to, which is solid, but not I was looking for.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mHR3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mHR3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png 424w, https://substackcdn.com/image/fetch/$s_!mHR3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png 848w, https://substackcdn.com/image/fetch/$s_!mHR3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png 1272w, https://substackcdn.com/image/fetch/$s_!mHR3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mHR3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png" width="800" height="50" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:50,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mHR3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png 424w, https://substackcdn.com/image/fetch/$s_!mHR3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png 848w, https://substackcdn.com/image/fetch/$s_!mHR3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png 1272w, https://substackcdn.com/image/fetch/$s_!mHR3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89f19bfb-e352-410b-9350-99f1afcc3781_800x50.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Apple Connect User Profile&#8202;&#8212;&#8202;Developer Response</figcaption></figure></div><p>I then found <a href="https://developer.apple.com/forums/thread/94013?page=1#719148022">this post</a> on the Apple Developer Forum, which as usual, didn&#8217;t have an easy answer. However, there was a useful data point about App Store review data being available by region via RSS (XML) or JSON.</p><blockquote><p>https://itunes.apple.com/&lt;countryCode&gt;/rss/customerreviews/id=&lt;appId&gt;/sortby=mostrecent/xml</p></blockquote><p>I tested that on my app and was happy to at least see some data come through.</p><ul><li><p><strong>JSON</strong>: <a href="https://itunes.apple.com/us/rss/customerreviews/id=1482090288/sortby=mostrecent/json">https://itunes.apple.com/us/rss/customerreviews/id=1482090288/sortby=mostrecent/json</a></p></li><li><p><strong>RSS Feed</strong>: <a href="https://itunes.apple.com/us/rss/customerreviews/id=1482090288/sortby=mostrecent/json">https://itunes.apple.com/us/rss/customerreviews/id=1482090288/sortby=mostrecent/</a>xml</p></li></ul><p>I then discovered that <a href="https://zapier.com/">Zapier</a> has an <a href="https://zapier.com/help/create/other-functions/trigger-zaps-from-new-rss-feed-items">RSS Feed Trigger</a>. Given that Zapier lets me have 5 free Zaps, I decided trying it out would be an acceptable solution, since I don&#8217;t have to make monthly payments if I just want to use this one Zap.</p><p>So I went ahead and configured my trigger as follows:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vahc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vahc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png 424w, https://substackcdn.com/image/fetch/$s_!vahc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png 848w, https://substackcdn.com/image/fetch/$s_!vahc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png 1272w, https://substackcdn.com/image/fetch/$s_!vahc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vahc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png" width="800" height="301" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c5ca693-869d-4484-8d38-774356a83c43_800x301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:301,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vahc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png 424w, https://substackcdn.com/image/fetch/$s_!vahc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png 848w, https://substackcdn.com/image/fetch/$s_!vahc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png 1272w, https://substackcdn.com/image/fetch/$s_!vahc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c5ca693-869d-4484-8d38-774356a83c43_800x301.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Zapier Trigger for New iOS App Store Review in a Region</figcaption></figure></div><p>Then I connected the Trigger to a Slack Action.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cWOT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cWOT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png 424w, https://substackcdn.com/image/fetch/$s_!cWOT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png 848w, https://substackcdn.com/image/fetch/$s_!cWOT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png 1272w, https://substackcdn.com/image/fetch/$s_!cWOT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cWOT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png" width="800" height="642" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:642,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cWOT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png 424w, https://substackcdn.com/image/fetch/$s_!cWOT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png 848w, https://substackcdn.com/image/fetch/$s_!cWOT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png 1272w, https://substackcdn.com/image/fetch/$s_!cWOT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c1b0808-388e-43d7-a4bb-a787661819cb_800x642.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I tested the trigger and got a good looking message. It literally took a minute.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Q_f_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Q_f_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png 424w, https://substackcdn.com/image/fetch/$s_!Q_f_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png 848w, https://substackcdn.com/image/fetch/$s_!Q_f_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png 1272w, https://substackcdn.com/image/fetch/$s_!Q_f_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Q_f_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png" width="800" height="212" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:212,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Q_f_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png 424w, https://substackcdn.com/image/fetch/$s_!Q_f_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png 848w, https://substackcdn.com/image/fetch/$s_!Q_f_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png 1272w, https://substackcdn.com/image/fetch/$s_!Q_f_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43a0cd25-a286-4323-a4e9-b81b65ef441a_800x212.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">iOS App Store Review Notification</figcaption></figure></div><p>As I was writing this post, with a bit more Google searching, I discovered that there is an <a href="https://developer.apple.com/app-store-connect/">App Connect</a> app created by Apple, which lets you get in app notification for new app store reviews.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nLG3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nLG3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg 424w, https://substackcdn.com/image/fetch/$s_!nLG3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg 848w, https://substackcdn.com/image/fetch/$s_!nLG3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!nLG3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nLG3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg" width="800" height="1733" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1733,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nLG3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg 424w, https://substackcdn.com/image/fetch/$s_!nLG3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg 848w, https://substackcdn.com/image/fetch/$s_!nLG3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!nLG3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc516ab9-16f7-4e1b-bb3e-a19cc4ebdbd9_800x1733.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">App Store Connect app Notifications for App Reviews</figcaption></figure></div><p>I wish that was more easily discoverable!</p><p>Anyways, if you work by yourself on your own app, or part of a small team, I recommend you just use the App Connect app.</p><p>Otherwise, if you&#8217;d like to route notifications to an email list or a Slack channel shared with your team, then it should also be as simple as this one minute Zap I shared in this post!</p><p>Hope you&#8217;ll find this useful. Enjoy!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Connecting Jira and Slack to Alert on SLA’s]]></title><description><![CDATA[Moved from Medium. Original Post Date: Jan 22 2022.]]></description><link>https://www.ali-b.com/p/connecting-jira-and-slack-to-alert</link><guid isPermaLink="false">https://www.ali-b.com/p/connecting-jira-and-slack-to-alert</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:39:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!9uLC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you use Jira and work on a team where you constantly need to stay on top of SLA&#8217;s, then this simple Jira + Slack integration will help you stay on top of SLA&#8217;s with minimal effort.</p><p>It basically automates away the act of worrying about SLA&#8217;s by sending your team a Slack message for any item nearing SLA, so you or your team can tag each other and respond with next steps on how you will meet this SLA.</p><p>Here is an example of what an alert/reminder might look like in Slack. If this looks like something you would like to enable for your team, read on for steps on how to make it happen!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!w-Lw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!w-Lw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png 424w, https://substackcdn.com/image/fetch/$s_!w-Lw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png 848w, https://substackcdn.com/image/fetch/$s_!w-Lw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png 1272w, https://substackcdn.com/image/fetch/$s_!w-Lw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!w-Lw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png" width="741" height="245" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:245,&quot;width&quot;:741,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!w-Lw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png 424w, https://substackcdn.com/image/fetch/$s_!w-Lw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png 848w, https://substackcdn.com/image/fetch/$s_!w-Lw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png 1272w, https://substackcdn.com/image/fetch/$s_!w-Lw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33950253-e40d-40a5-8b74-3e6e68c031d5_741x245.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Slack Alert Message for an SLA</figcaption></figure></div><h3>Solution</h3><p><a href="https://www.atlassian.com/software/jira/automation-template-library#/">Jira automation</a> capabilities give a lot of control, letting you find the exact issue you want.</p><p>To get started, go to your Jira project, settings, and click Automation.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nv5b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nv5b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png 424w, https://substackcdn.com/image/fetch/$s_!nv5b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png 848w, https://substackcdn.com/image/fetch/$s_!nv5b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png 1272w, https://substackcdn.com/image/fetch/$s_!nv5b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nv5b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png" width="1012" height="288" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:288,&quot;width&quot;:1012,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nv5b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png 424w, https://substackcdn.com/image/fetch/$s_!nv5b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png 848w, https://substackcdn.com/image/fetch/$s_!nv5b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png 1272w, https://substackcdn.com/image/fetch/$s_!nv5b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9652b47e-1f9e-4e6d-bc5a-cf8d2ad586e2_1012x288.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Jira Automation Rules</figcaption></figure></div><p>Create a &#8220;scheduled&#8221; rule. Pick CRON scheduling since we want the control to only run the rule during weekdays. Also, since the CRON rules are in UTC, if you want the rule to run 9 am PST, the time picked in CRON should be 16 (9 am PST = 4 pm UTC)</p><p><em>0 15 16 ? * MON-FRI</em></p><blockquote><p>Pick a query to detect the needle in the haystack that you&#8217;re looking for.</p></blockquote><p>For example, to find all customer bugs that are nearing SLA (even when no due date is specified):</p><p><em>labels = customer-bug AND priority in (P1, P2, P3) AND status != CLOSED AND (due &lt; 7d OR due is EMPTY AND (priority = P1 AND createdDate &lt; -7d OR priority = P2 AND createdDate &lt; -23d OR priority = P3 AND createdDate &lt; -53d))</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9uLC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9uLC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png 424w, https://substackcdn.com/image/fetch/$s_!9uLC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png 848w, https://substackcdn.com/image/fetch/$s_!9uLC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png 1272w, https://substackcdn.com/image/fetch/$s_!9uLC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9uLC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png" width="800" height="402" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:402,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9uLC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png 424w, https://substackcdn.com/image/fetch/$s_!9uLC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png 848w, https://substackcdn.com/image/fetch/$s_!9uLC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png 1272w, https://substackcdn.com/image/fetch/$s_!9uLC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8e5dbb9-5c93-4772-98d3-8ba47e9134ec_800x402.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Scheduled Automation Rule in Jira</figcaption></figure></div><p>Next, you can configure the detected issues to be sent over to a team Slack channel. Although Jira has an out of the box action to &#8220;Send to Slack&#8221;, it requires Slack admin permissions to be able to send messages to Slack, which most of us don&#8217;t have.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ngG9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ngG9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png 424w, https://substackcdn.com/image/fetch/$s_!ngG9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png 848w, https://substackcdn.com/image/fetch/$s_!ngG9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png 1272w, https://substackcdn.com/image/fetch/$s_!ngG9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ngG9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png" width="582" height="342" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:342,&quot;width&quot;:582,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ngG9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png 424w, https://substackcdn.com/image/fetch/$s_!ngG9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png 848w, https://substackcdn.com/image/fetch/$s_!ngG9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png 1272w, https://substackcdn.com/image/fetch/$s_!ngG9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f2fba09-ba00-421b-b43e-d569317b6198_582x342.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Jira Automation Slack Action</figcaption></figure></div><p>Here is what you&#8217;d get if you try to configure the webhook.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oPKh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oPKh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png 424w, https://substackcdn.com/image/fetch/$s_!oPKh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png 848w, https://substackcdn.com/image/fetch/$s_!oPKh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png 1272w, https://substackcdn.com/image/fetch/$s_!oPKh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oPKh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png" width="800" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4339926-df74-4872-91e1-9e4e93accc2c_800x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!oPKh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png 424w, https://substackcdn.com/image/fetch/$s_!oPKh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png 848w, https://substackcdn.com/image/fetch/$s_!oPKh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png 1272w, https://substackcdn.com/image/fetch/$s_!oPKh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4339926-df74-4872-91e1-9e4e93accc2c_800x210.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Only Workspace Admins can configure the Slack webhook!</figcaption></figure></div><p>Luckily, there is an alternative to sending a message to Slack. Everyone should have permission to create workflows in Slack.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!21mG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!21mG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png 424w, https://substackcdn.com/image/fetch/$s_!21mG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png 848w, https://substackcdn.com/image/fetch/$s_!21mG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png 1272w, https://substackcdn.com/image/fetch/$s_!21mG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!21mG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png" width="624" height="392" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:392,&quot;width&quot;:624,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!21mG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png 424w, https://substackcdn.com/image/fetch/$s_!21mG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png 848w, https://substackcdn.com/image/fetch/$s_!21mG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png 1272w, https://substackcdn.com/image/fetch/$s_!21mG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb020a90e-cf25-4765-997b-102a6e5b1f79_624x392.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">How to open the Slack Workflow Builder</figcaption></figure></div><p>After creating the workflow in Slack, add a new webhook trigger, give it all of the variables (parameters), so they could get passed dynamically from Jira.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VaBB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VaBB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png 424w, https://substackcdn.com/image/fetch/$s_!VaBB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png 848w, https://substackcdn.com/image/fetch/$s_!VaBB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png 1272w, https://substackcdn.com/image/fetch/$s_!VaBB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VaBB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png" width="500" height="525" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:525,&quot;width&quot;:500,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VaBB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png 424w, https://substackcdn.com/image/fetch/$s_!VaBB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png 848w, https://substackcdn.com/image/fetch/$s_!VaBB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png 1272w, https://substackcdn.com/image/fetch/$s_!VaBB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd245fed7-7e0f-44e1-a834-dbadbaed6186_500x525.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Slack Workflow Builder Webhook trigger with Variables</figcaption></figure></div><p>Then add an action to &#8220;Send a message&#8221; and configure the message to go to your desired Slack channel and have the variables in the message content formatted the way you like.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!v_Xw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!v_Xw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png 424w, https://substackcdn.com/image/fetch/$s_!v_Xw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png 848w, https://substackcdn.com/image/fetch/$s_!v_Xw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png 1272w, https://substackcdn.com/image/fetch/$s_!v_Xw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!v_Xw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png" width="505" height="598" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:598,&quot;width&quot;:505,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!v_Xw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png 424w, https://substackcdn.com/image/fetch/$s_!v_Xw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png 848w, https://substackcdn.com/image/fetch/$s_!v_Xw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png 1272w, https://substackcdn.com/image/fetch/$s_!v_Xw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938a9f1d-40fa-4126-8966-7c0fb56a4ddd_505x598.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Slack Send Message Action</figcaption></figure></div><p>Here is a preview of what the Workflow in Slack looks like at a high level. Copy the URL of the web request that starts the Slack workflow so you can use it in the Jira automation configuration.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!q2q2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!q2q2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png 424w, https://substackcdn.com/image/fetch/$s_!q2q2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png 848w, https://substackcdn.com/image/fetch/$s_!q2q2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png 1272w, https://substackcdn.com/image/fetch/$s_!q2q2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!q2q2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png" width="837" height="540" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:540,&quot;width&quot;:837,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!q2q2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png 424w, https://substackcdn.com/image/fetch/$s_!q2q2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png 848w, https://substackcdn.com/image/fetch/$s_!q2q2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png 1272w, https://substackcdn.com/image/fetch/$s_!q2q2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c388a32-98a3-44b1-82d6-68755ee22730_837x540.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Preview of Slack Workflow</figcaption></figure></div><p>You only need to configure one Slack Jira workflow, and then connect all your Jira automations to that Slack webhook. Go back to the Jira automation and add an action to &#8220;Send web request&#8221;. Use <a href="https://confluence.atlassian.com/servicemanagementserver/advanced-placeholders-1044784599.html">Jira placeholders</a> to pass details to Slack that make the alert message relevant, concise, timely and actionable!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!utwq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!utwq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png 424w, https://substackcdn.com/image/fetch/$s_!utwq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png 848w, https://substackcdn.com/image/fetch/$s_!utwq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png 1272w, https://substackcdn.com/image/fetch/$s_!utwq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!utwq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png" width="800" height="633" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:633,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!utwq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png 424w, https://substackcdn.com/image/fetch/$s_!utwq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png 848w, https://substackcdn.com/image/fetch/$s_!utwq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png 1272w, https://substackcdn.com/image/fetch/$s_!utwq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca173177-b75d-48fb-b96c-60c6dc0fd500_800x633.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Jira Send Web Request Action</figcaption></figure></div><p>That&#8217;s it. You&#8217;re done! This should be quick and easy once you familiarize yourself a bit with Jira Query Language (JQL).</p><h3>Conclusion</h3><p>Basically, every single Jira ticket that has an SLA could be surfaced with its own workflow in Jira and very clear calls to action. This all depends on how large your company is, potentially having 1 workflow if you are a small startup, while having 10&#8217;s of workflows if you are a large mature company with processes/demands from customers coming from multiple directions.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LooK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LooK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png 424w, https://substackcdn.com/image/fetch/$s_!LooK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png 848w, https://substackcdn.com/image/fetch/$s_!LooK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png 1272w, https://substackcdn.com/image/fetch/$s_!LooK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LooK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png" width="800" height="269" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:269,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LooK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png 424w, https://substackcdn.com/image/fetch/$s_!LooK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png 848w, https://substackcdn.com/image/fetch/$s_!LooK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png 1272w, https://substackcdn.com/image/fetch/$s_!LooK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5c0ea2f-2b8b-45df-b72b-4ace53070a87_800x269.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>As simple as this looks, I&#8217;ve applied this on my team and it&#8217;s tremendously helped us stay consistently on top of SLA&#8217;s and heavily reduced the collective cognitive load in our organization for keeping track of SLA&#8217;s. It&#8217;s usually the simple things that end up working the best, so I hope you&#8217;d get the chance to apply this on your own team!</p><p>Enjoy!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Personal Kanban with Trello]]></title><description><![CDATA[Moved from Medium. Original post date: Oct 29th 2021.]]></description><link>https://www.ali-b.com/p/personal-kanban-with-trello</link><guid isPermaLink="false">https://www.ali-b.com/p/personal-kanban-with-trello</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:36:27 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7FB5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Introduction</h3><p>We live in a world where we&#8217;re bombarded with tons of things that demand our attention and time, yet without enough hours in the day or years in life to get it done.</p><p>We end up with huge Todo lists that grow quickly in size and become overwhelming to read, making it hard to identify what to work on next. For those of us that learned how to leverage calendars, we end up spending time moving allocated slots around because they either take up more time or their priority changes.</p><p>I am not saying checklists and calendars should not be put to good use. However, given the fact that we&#8217;re still overwhelmed and unfocused, we need a process that is extremely simple AND flexible, where it almost costs no time to identify the next highest priority task and get it done!</p><p>In other words, we need &#8220;a process that hates process&#8221;. A process that can:</p><ul><li><p>Handle the dichotomy of flexibility and simplicity</p></li><li><p>Leave us with a feeling of control and a pleasure of accomplishment</p></li><li><p>Make the conceptual tangible and the ambiguous actionable</p></li><li><p>Not get messy and overwhelming over time</p></li></ul><p>We need a Personal Kanban system! In this post, I will show you how to leverage Trello to build your own super simple Personal Kanban. Reading the book <a href="https://www.amazon.com/Four-Thousand-Weeks-Management-Mortals/dp/0374159122">Four Thousand Weeks: Time Management for Mortals</a> inspired me to start using a &#8220;Top 3&#8221; Kanban board, and I leveraged the book <a href="https://www.amazon.com/Personal-Kanban-Mapping-Work-Navigating/dp/1453802266">Personal Kanban: Mapping Work | Navigating Life</a> to help refine my mindset about how to leverage this simple tool.</p><h3>What is Personal Kanban?</h3><p>Personal Kanban is intended to be simple. It boils down to:</p><ul><li><p>Visualizing your work</p></li><li><p>Limiting your WIP (Work in progress)</p></li><li><p>Breaking down your work into achievable chunks</p></li></ul><p>If you do not know what a Kanban board is, I highly recommend you read this post from Atlassian about <a href="https://www.atlassian.com/agile/kanban/boards">What is a Kanban board?</a></p><p>Our Kanban board will mainly be composed of three columns or lists.</p><ul><li><p>Top 3</p></li><li><p>Won&#8217;t Do</p></li><li><p>Done</p></li></ul><div><hr></div><h3>The &#8220;Top 3&#8221; Lane</h3><p>When we visualize our work, what we need to do becomes a lot more tangible. As a result, we start actively seeking out opportunities for improvement (i.e. a kaizen mindset).</p><p>We can&#8217;t do more work than we can handle. Our brains can remember very few important things, and the more we have of those, the less we can stay focused and get any of them done.</p><p>It&#8217;s very common in Kanban boards to have separate &#8220;To Do&#8221; and &#8220;In Progress&#8217;&#8217; columns. For personal use, however, I think there is no point in having our brain procrastinate on what we want to do next. Instead, we merge &#8220;To Do&#8221; and &#8220;In Progress&#8217;&#8217; into one column and limit the number of cards to three. That&#8217;s why we call it the &#8220;Top 3&#8221; list, and it includes the top three things that we want to do or are already doing.</p><p>When we do that, we force our brains to only think about the top three things that matter and on getting them done in sequence. If you can parallelize on more than three tasks at the same time without getting overwhelmed, go for it and increase the limit.</p><h3>On planning the day</h3><p>But what about being intentional and starting the day with calling the shots about what you want to achieve? Wouldn&#8217;t separating the &#8220;To Do&#8221; and &#8220;In Progress&#8221; columns help us do just that?</p><p>Maybe.</p><p>When my head is cloudy and I am unclear about what to do, I find journaling to be the most effective method to declutter my brain, by answering the following three questions:</p><ul><li><p>What am I grateful for?</p></li><li><p>What would make today great?</p></li><li><p>What am I worried about?</p></li></ul><p>So instead of bringing in my cluttered thoughts into the Kanban board, I rely on journaling to find clarity.</p><blockquote><p>Clarity drives prioritization, completion and effectiveness.</p></blockquote><div><hr></div><h3>The &#8220;Won&#8217;t Do&#8221; List</h3><p>Now of course, there might be a lot on your mind than those top three things, so just put them for now in the &#8220;Won&#8217;t Do&#8221; list. In scrum speak, this is what is called the &#8220;Backlog&#8221; or &#8220;To Do&#8221;, but we are calling it the &#8220;Won&#8217;t Do&#8221; list to tell our brains that this is something that we&#8217;re not going to do right now and it&#8217;s not one of the most important three things we should be doing.</p><p>And yes, new things will come up that look very urgent and important, and those would go to the &#8220;Won&#8217;t Do&#8221; list unless you think they&#8217;re actually more important. What matters is for the WIP lane to never grow beyond three (or your limit), otherwise, you&#8217;ll clutter your mind and intensify your time anxiety. By limiting what you are doing, you learn to care to finish what you begin.</p><h3>Why I chose the name &#8220;Won&#8217;t Do&#8221; for the Backlog</h3><p>According to <a href="https://www.amazon.com/Four-Thousand-Weeks-Management-Mortals/dp/0374159122">Four Thousand Weeks: Time Management for Mortals</a>, the real measure of any time management technique is whether or not it helps you neglect the right things. Most of our anxieties, Burkeman argues, derive from a nagging sense that we might be wasting what little time we have. Procrastination is unavoidable, though we can get better at ignoring the right things. Missing out is basically guaranteed in life, the inevitable consequence of one path chosen over another. We should pursue the activities we intrinsically enjoy while accepting our finitude and committing to what&#8217;s most important.</p><div><hr></div><h3>The &#8220;Done&#8221; List</h3><p>This list consists of the work that we have completed.</p><p>The key is to focus on limiting WIP and completing tasks first. When you pull one card into the &#8220;Done&#8221; list, you are fully ready now to work on the next task without distractions. You do this over and over, respecting your WIP limit, and you start feeling that you are now able to do the optimal amount of work at the optimal speed!</p><h3>Retrospection</h3><p>I like to put in the name of the Done list the month (ex: Done Oct 2021) so I can keep track and retrospect on the work I am doing each week. The more that you look for an opportunity to improve, the more likely you will find one.</p><p>At the beginning or end of each week, hold a retrospective and quickly examine completed tasks. Acknowledge what went well and what could be improved next time. Were you effectively doing tasks you are not particularly good at? Was the work fulfilling? Were there things you could have refused or delegated? Was your week balanced between career, family, and personal development? Were you happy doing what you&#8217;re doing, as that might be your best measure of success!</p><h3>Breaking Things Down</h3><p>There is a phenomenon, known as the &#8220;Zeigarnik Effect&#8221;, that states that adults have a 90% chance of remembering interrupted and incomplete thoughts or actions over those that have been seen through to completion.</p><p>So when you pick a task and feel it is too much work to do for the day, take a manageable chunk from it and make it your current task. Think for example, which task can fit into the half hour before a meeting? While we want to reduce task size to make our work more manageable, we shouldn&#8217;t become restrained by the process and mired in detail. So break down as you do rather than trying to break it all down at the beginning. Remaining flexible enough to adapt and prioritize on the fly is key since we want to do the right thing, right now. Thoughtful prioritization and completion beats rigorous upfront planning.</p><p>Do not confuse this with team projects that need to be broken down all the way and buffered for predictability of delivery.</p><p>If there is a task that is pending action from others, either create a new one or move it to the top of the &#8220;Won&#8217;t Do&#8221; list to be picked up later.</p><div><hr></div><h3>Personal Kanban in Trello</h3><p><a href="https://trello.com/">Trello</a> is a web-based, Kanban-style, list-making application, we&#8217;ll use to create the Personal Kanban system we&#8217;ve described earlier.</p><p>Create a new board in Trello with the following three columns (or lists to use a Trello term). You can also give &#8220;Top 3&#8221; a name like &#8220;WIP&#8221;, or give the &#8220;Won&#8217;t Do&#8221; list a name like &#8220;To Do&#8221; or &#8220;BackLog&#8221;. Pick the names you prefer.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Mi2J!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Mi2J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png 424w, https://substackcdn.com/image/fetch/$s_!Mi2J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png 848w, https://substackcdn.com/image/fetch/$s_!Mi2J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png 1272w, https://substackcdn.com/image/fetch/$s_!Mi2J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Mi2J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png" width="800" height="105" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:105,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Mi2J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png 424w, https://substackcdn.com/image/fetch/$s_!Mi2J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png 848w, https://substackcdn.com/image/fetch/$s_!Mi2J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png 1272w, https://substackcdn.com/image/fetch/$s_!Mi2J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80e8e24a-13d2-4701-9a1b-1ae206aef6bd_800x105.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Configure a rule to set the date of a card that you add to the &#8220;Top 3&#8221; list to 16 hours from now, since if you&#8217;re adding it to your top 3, you gotta shoot to get it done today or early tomorrow.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7FB5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7FB5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png 424w, https://substackcdn.com/image/fetch/$s_!7FB5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png 848w, https://substackcdn.com/image/fetch/$s_!7FB5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png 1272w, https://substackcdn.com/image/fetch/$s_!7FB5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7FB5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png" width="800" height="806" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:806,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7FB5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png 424w, https://substackcdn.com/image/fetch/$s_!7FB5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png 848w, https://substackcdn.com/image/fetch/$s_!7FB5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png 1272w, https://substackcdn.com/image/fetch/$s_!7FB5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0993edd-08bc-4b91-b949-e9e4c3642be7_800x806.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YGHf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YGHf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png 424w, https://substackcdn.com/image/fetch/$s_!YGHf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png 848w, https://substackcdn.com/image/fetch/$s_!YGHf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png 1272w, https://substackcdn.com/image/fetch/$s_!YGHf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YGHf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png" width="606" height="862" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:862,&quot;width&quot;:606,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YGHf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png 424w, https://substackcdn.com/image/fetch/$s_!YGHf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png 848w, https://substackcdn.com/image/fetch/$s_!YGHf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png 1272w, https://substackcdn.com/image/fetch/$s_!YGHf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1a6873d-aa7e-4936-a567-7ed1dd4300c5_606x862.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Then, configure the &#8220;Done&#8221; list to mark the Due date as completed when a card is moved to it. Finally, add a custom rule to the &#8220;Top 3&#8221; to prevent it from ever going beyond 3 cards by moving the added card back to the &#8220;Won&#8217;t Do&#8221; list.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yTfc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yTfc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png 424w, https://substackcdn.com/image/fetch/$s_!yTfc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png 848w, https://substackcdn.com/image/fetch/$s_!yTfc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png 1272w, https://substackcdn.com/image/fetch/$s_!yTfc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yTfc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png" width="800" height="481" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:481,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yTfc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png 424w, https://substackcdn.com/image/fetch/$s_!yTfc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png 848w, https://substackcdn.com/image/fetch/$s_!yTfc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png 1272w, https://substackcdn.com/image/fetch/$s_!yTfc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa80f01-409e-416b-96b1-e2ca24fc688a_800x481.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>As you add your first 3 tasks, all is good. Since right now is Oct 10th 3 pm, the due date was automatically set for 16 hours from now when the card was added.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7BHP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7BHP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png 424w, https://substackcdn.com/image/fetch/$s_!7BHP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png 848w, https://substackcdn.com/image/fetch/$s_!7BHP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png 1272w, https://substackcdn.com/image/fetch/$s_!7BHP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7BHP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png" width="800" height="293" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/da403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:293,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7BHP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png 424w, https://substackcdn.com/image/fetch/$s_!7BHP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png 848w, https://substackcdn.com/image/fetch/$s_!7BHP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png 1272w, https://substackcdn.com/image/fetch/$s_!7BHP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda403e50-d14f-4e0b-8633-d0c727fb6f88_800x293.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When you added a fourth card to the list beyond your capacity, the card got automatically moved to the &#8220;Won&#8217;t do&#8221; List. This way, you focus on your top 3 and that&#8217;s it. If you want to re-prioritize what goes into your top 3 list, you can always move out the cards that are lower priority to the &#8220;Won&#8217;t Do&#8221; list.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!21QG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!21QG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png 424w, https://substackcdn.com/image/fetch/$s_!21QG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png 848w, https://substackcdn.com/image/fetch/$s_!21QG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png 1272w, https://substackcdn.com/image/fetch/$s_!21QG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!21QG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png" width="800" height="290" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:290,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!21QG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png 424w, https://substackcdn.com/image/fetch/$s_!21QG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png 848w, https://substackcdn.com/image/fetch/$s_!21QG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png 1272w, https://substackcdn.com/image/fetch/$s_!21QG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F582bbb16-ba29-48ce-a31c-a3599bfdd506_800x290.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>After a little bit of usage, your board would look something like this.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Cn1o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Cn1o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png 424w, https://substackcdn.com/image/fetch/$s_!Cn1o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png 848w, https://substackcdn.com/image/fetch/$s_!Cn1o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png 1272w, https://substackcdn.com/image/fetch/$s_!Cn1o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Cn1o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png" width="800" height="299" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/baad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:299,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Cn1o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png 424w, https://substackcdn.com/image/fetch/$s_!Cn1o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png 848w, https://substackcdn.com/image/fetch/$s_!Cn1o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png 1272w, https://substackcdn.com/image/fetch/$s_!Cn1o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaad3cd1-6f7c-408f-8ac5-051bab2f8816_800x299.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>But there is a catch</h3><p>After using this system for a few weeks, I got an email from Trello that I am reaching my monthly limit for Butler quota. I didn&#8217;t honestly know what Butler is, so I went and searched their website and realized it is the basic automation actions that automatically added a due date to a card when placed in the lane.</p><p>I realized that I created a system that is not free. I went online to check the pricing. I am paying for Netflix, HBO, Spotify, <a href="https://shahid.mbc.net/">Shahid</a>, etc&#8230; Why am I being cheap about investing $5 a month in a system that has helped me get a sense of control on my tasks and held me accountable to stay focused on the top things that matter? I&#8217;ve decided to go ahead and subscribe. If you want your system not to cost you anything, simply do not use the automation rules. They&#8217;re not really that necessary as long as you&#8217;re following the rules of keeping WIP up to three.</p><h3>Customize, but don&#8217;t get held back by it</h3><p>Over time, customize your work to match your reality. For example, separate personal, health and side projects into their own columns (or swimlanes). You might get tempted to start adding a lot of columns. For example, week, month and quarter columns. Although this looks like an act of prioritizing what is most important first, it quickly begins adding a lot of complexity and you find yourself spending time prioritizing things around instead of doing what matters most now! In other words, only add another column if you think it&#8217;s necessary and it will help keep things simple.</p><blockquote><p>Real-time flexibility beats rigid up-front planning.</p></blockquote><p>This is what my board looks like. For example, I have a column for &#8220;Health&#8221; because I think it matters and needs to be prioritized with other things happening at work and life.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2C31!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2C31!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png 424w, https://substackcdn.com/image/fetch/$s_!2C31!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png 848w, https://substackcdn.com/image/fetch/$s_!2C31!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png 1272w, https://substackcdn.com/image/fetch/$s_!2C31!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2C31!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png" width="800" height="394" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:394,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2C31!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png 424w, https://substackcdn.com/image/fetch/$s_!2C31!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png 848w, https://substackcdn.com/image/fetch/$s_!2C31!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png 1272w, https://substackcdn.com/image/fetch/$s_!2C31!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa7e369c-9e10-42a4-8602-cb523567bd34_800x394.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h3>Conclusion</h3><p>Although I believe firmly that I have shared with you a mechanism for optimizing your productivity, efficiency and effectiveness, don&#8217;t let that turn you into a working machine.</p><p>Don&#8217;t forget to spend time on things that have intrinsic value to you. If you can&#8217;t find a way to be happy now, at this moment, you probably never will be, no matter how many to-do items you cross off your list.</p><p>Make time for what you enjoy in life, even if it is not important or urgent.</p><blockquote><p>Time you enjoy wasting, was not wasted&#8202;&#8212;&#8202;John Lennon.</p></blockquote><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Handstand Quest]]></title><description><![CDATA[Moving from Medium. Original post Oct 23 2019.]]></description><link>https://www.ali-b.com/p/handstand-quest</link><guid isPermaLink="false">https://www.ali-b.com/p/handstand-quest</guid><dc:creator><![CDATA[Ali B]]></dc:creator><pubDate>Fri, 01 Aug 2025 14:33:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!e3hx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;ve been trying to find ways to motivate myself to do handstands daily and improve the time I can hold a handstand.</p><h3>The Search</h3><p>To do so, I started looking for a mechanism that can help me track the length of handstand holds, within minimal effort, so I can focus on practicing rather than log keeping. Clearly, the key was that the tracking needed to happen hands free.</p><p>I started by leveraging the Gyroscope on a phone, and then realized it&#8217;s not that practical to attach a phone on me while I am attempting a handstand. It generally falls out of pocket, if I happen to be wearing anything with pockets. And to be honest, it&#8217;s a lot of overhead to be wearing a waist belt with pockets anytime I want to feel motivated to do handstands. I started thinking about a specialized small device that attaches to the foot, but then again, it is yet another device that needs to be charged, worn, and put somewhere so it won&#8217;t get lost.</p><h3>The Solution</h3><p>When I thought I ran out of options, I realized that using voice could be promising. It&#8217;s hands free, doesn&#8217;t require any setup, and does not force me to attach something to my body. I also wanted something without that tax of having to say &#8220;Hey Siri/Google, start my app X&#8221; every time. To put it to the test, I started building an iPhone app to see how it would turn out and whether it could actually be practical. And voil&#224;, I think I&#8217;ve put together an MVP for the first mobile app of its kind that leverages voice commands to guide a workout, one exercise at a time.</p><h3>Let&#8217;s Win Together</h3><p>Before rolling it out to the app store, I want to figure out if the current minimum set of functionality that I&#8217;ve put together is enough to help someone, other than myself, improve their own handstand hold time.</p><blockquote><p>If you&#8217;ve read so far, it means you&#8217;re serious about handstands, and I think we have a win-win.</p></blockquote><p>If you use the app daily for 7 days, a heart icon will show up in the app, so you can provide your feedback on your experience with the app. Once your feedback is submitted, I will record your name to give you lifetime access to the app for free, including all future updates and improvements I make to it on all platforms.</p><p>If you are interested, follow the steps below to join me on this Handstand Quest!</p><h3>Sneak Peak (Oct 2019)</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e3hx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e3hx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png 424w, https://substackcdn.com/image/fetch/$s_!e3hx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png 848w, https://substackcdn.com/image/fetch/$s_!e3hx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png 1272w, https://substackcdn.com/image/fetch/$s_!e3hx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e3hx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png" width="400" height="866" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:866,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e3hx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png 424w, https://substackcdn.com/image/fetch/$s_!e3hx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png 848w, https://substackcdn.com/image/fetch/$s_!e3hx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png 1272w, https://substackcdn.com/image/fetch/$s_!e3hx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d03ae9c-3e3a-479e-a563-39460be772ac_400x866.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!q_bj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!q_bj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png 424w, https://substackcdn.com/image/fetch/$s_!q_bj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png 848w, https://substackcdn.com/image/fetch/$s_!q_bj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png 1272w, https://substackcdn.com/image/fetch/$s_!q_bj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!q_bj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png" width="400" height="866" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:866,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!q_bj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png 424w, https://substackcdn.com/image/fetch/$s_!q_bj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png 848w, https://substackcdn.com/image/fetch/$s_!q_bj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png 1272w, https://substackcdn.com/image/fetch/$s_!q_bj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0019dfd4-9a9e-47d7-8b3f-5b0d056d3641_400x866.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SYcf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SYcf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png 424w, https://substackcdn.com/image/fetch/$s_!SYcf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png 848w, https://substackcdn.com/image/fetch/$s_!SYcf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png 1272w, https://substackcdn.com/image/fetch/$s_!SYcf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SYcf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png" width="400" height="866" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:866,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SYcf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png 424w, https://substackcdn.com/image/fetch/$s_!SYcf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png 848w, https://substackcdn.com/image/fetch/$s_!SYcf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png 1272w, https://substackcdn.com/image/fetch/$s_!SYcf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8204a817-867a-4b1f-89c1-fab6f4b16bde_400x866.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Steps to Join</h3><blockquote><p>Go to the website (<a href="https://www.handstandquest.com">https://www.handstandquest.com</a>) to get the App.</p></blockquote><p>Use the app for 7 days. After 7 days, a new button will light up in the top menu. Submit your feedback and continue to use the app as you see fit. I will be making updates based on your feedback, and you will receive those updates.</p><p>Enjoy handstanding and I am looking forward to hear how this app will help you improve your handstands!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.ali-b.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Ali&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>