<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stanley J</title>
    <description>The latest articles on DEV Community by Stanley J (@istealersn_dev).</description>
    <link>https://dev.to/istealersn_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png</url>
      <title>DEV Community: Stanley J</title>
      <link>https://dev.to/istealersn_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/istealersn_dev"/>
    <language>en</language>
    <item>
      <title>What is your take on n8n Automation workflows? Have you tried clubbing that with AI? I built an autonomous financial newsletter summarization that will give you key details you need instead of long form content</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Wed, 30 Jul 2025 12:35:25 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/what-is-your-take-on-n8n-automation-workflows-have-you-tried-clubbing-that-with-ai-i-built-an-bc8</link>
      <guid>https://dev.to/istealersn_dev/what-is-your-take-on-n8n-automation-workflows-have-you-tried-clubbing-that-with-ai-i-built-an-bc8</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/istealersn_dev/autonomous-email-summarization-5gml" class="crayons-story__hidden-navigation-link"&gt;Autonomous Email Summarization&lt;/a&gt;


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

          &lt;a href="/istealersn_dev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" alt="istealersn_dev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/istealersn_dev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Stanley J
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Stanley J
                
              
              &lt;div id="story-author-preview-content-2741140" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/istealersn_dev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Stanley J&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/istealersn_dev/autonomous-email-summarization-5gml" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 30 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/istealersn_dev/autonomous-email-summarization-5gml" id="article-link-2741140"&gt;
          Autonomous Email Summarization
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/automation"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;automation&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tooling"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tooling&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/istealersn_dev/autonomous-email-summarization-5gml#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>automation</category>
      <category>tooling</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Autonomous Email Summarization</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Wed, 30 Jul 2025 06:56:10 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/autonomous-email-summarization-5gml</link>
      <guid>https://dev.to/istealersn_dev/autonomous-email-summarization-5gml</guid>
      <description>&lt;h2&gt;
  
  
  Building an Autonomous Email Summarization Workflow with n8n, AI, and Obsidian
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;How I built a daily automation that fetches financial newsletters, summarizes them with AI, and saves clean markdown notes to Obsidian - completely hands-free.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Like many investors, I receive daily market newsletters packed with valuable insights. But who has time to read through lengthy emails every morning? I wanted an automation that could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fetch emails automatically&lt;/strong&gt; from specific senders&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extract and clean the content&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate intelligent summaries&lt;/strong&gt; using AI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save formatted notes&lt;/strong&gt; to my knowledge management system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run completely autonomous&lt;/strong&gt; - no manual intervention needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution Architecture
&lt;/h2&gt;

&lt;p&gt;After exploring various approaches, I settled on this tech stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;🕐 n8n&lt;/strong&gt;: Workflow automation and orchestration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📧 Gmail API&lt;/strong&gt;: Email fetching with smart filtering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🤖 Groq&lt;/strong&gt;: Free AI summarization (Llama models)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📝 Obsidian&lt;/strong&gt;: Knowledge management with Local REST API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;⚙️ PM2&lt;/strong&gt;: Process management for 24/7 operation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up the Daily Trigger
&lt;/h2&gt;

&lt;p&gt;The foundation is a schedule trigger that runs every day at 9:15 AM. This timing ensures I get summaries of yesterday’s emails right when I start my day.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Cron expression for 9:15 AM IST daily&lt;/span&gt;
&lt;span class="nx"&gt;Schedule&lt;/span&gt; &lt;span class="nx"&gt;Trigger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="nx"&gt;Timezone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Asia&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Kolkata&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key insight&lt;/strong&gt;: Always set the timezone explicitly to avoid confusion when testing vs production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Smart Email Filtering
&lt;/h2&gt;

&lt;p&gt;Rather than processing all emails repeatedly, I implemented dynamic date filtering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Only fetch emails from last 24 hours&lt;/span&gt;
&lt;span class="nx"&gt;Received&lt;/span&gt; &lt;span class="nx"&gt;After&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="nl"&gt;Sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;specific&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;newsletter&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Only new emails are processed daily&lt;/li&gt;
&lt;li&gt;No duplicate processing&lt;/li&gt;
&lt;li&gt;Efficient API usage&lt;/li&gt;
&lt;li&gt;Relevant, timely content&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Email Content Extraction
&lt;/h2&gt;

&lt;p&gt;Gmail API returns emails in a complex nested structure. The key was handling both plain text and HTML emails while cleaning up the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Extract email body from Gmail's complex structure&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;extractBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown Sender&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Extract subject and date from emailData&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No Subject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Prioritize plain text, fallback to cleaned HTML&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;emailBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;emailBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textAsHtml&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;emailBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;emailData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textAsHtml&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;p&amp;gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;p&amp;gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;br&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\/?&lt;/span&gt;&lt;span class="sr"&gt;&amp;gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;amp;nbsp;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*&amp;gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;emailBody&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lesson learned&lt;/strong&gt;: Always handle multiple email formats and include robust text cleaning for better AI processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: AI-Powered Summarization
&lt;/h2&gt;

&lt;p&gt;For AI summarization, I chose Groq for its generous free tier (14,400 requests/day) and fast inference. The key was crafting prompts specifically for financial content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Individual Summary Prompt:
Analyze and summarize this financial newsletter content focusing on:

"{text}"

Provide a CONCISE SUMMARY that includes:
&lt;span class="p"&gt;-&lt;/span&gt; Key stock recommendations and target prices
&lt;span class="p"&gt;-&lt;/span&gt; Important market insights and trends  
&lt;span class="p"&gt;-&lt;/span&gt; Sector analysis and opportunities
&lt;span class="p"&gt;-&lt;/span&gt; Risk factors or warnings mentioned
&lt;span class="p"&gt;-&lt;/span&gt; Actionable investment advice
&lt;span class="p"&gt;-&lt;/span&gt; Any time-sensitive information

Format the summary in clear bullet points for easy reading.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Customize your AI prompts for your specific domain. Generic summarization prompts don’t capture domain-specific insights effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Obsidian Integration Challenge
&lt;/h2&gt;

&lt;p&gt;This is where things got interesting. I initially tried Obsidian’s Local REST API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// HTTP Request to Obsidian Local REST API&lt;/span&gt;
&lt;span class="nx"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PUT&lt;/span&gt;
&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//127.0.0.1:27124/vault/VaultName/filename.md&lt;/span&gt;
&lt;span class="nx"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Bearer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: Obsidian API returns HTTP 204 “No Content” on successful file creation, which n8n’s HTTP Request node can’t parse properly, causing server log errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  The n8n HTTP 204 Bug
&lt;/h2&gt;

&lt;p&gt;After extensive debugging, I discovered this is a &lt;strong&gt;known limitation in n8n&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File gets created successfully&lt;/strong&gt; in Obsidian&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow completes&lt;/strong&gt; and functions correctly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server logs show parsing errors&lt;/strong&gt; due to empty response body&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The research revealed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple GitHub issues (&lt;a href="https://github.com/n8n-io/n8n/issues/11283" rel="noopener noreferrer"&gt;#11283&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Community forum requests for better 204 handling&lt;/li&gt;
&lt;li&gt;This affects many APIs that return 204 responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Current workarounds&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable “Never Error” option&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable “Include Response Headers and Status”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accept the log noise (functionality works fine)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 6: Production Deployment with PM2
&lt;/h2&gt;

&lt;p&gt;Running automation workflows requires 24/7 operation. PM2 was the perfect solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install PM2&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2

&lt;span class="c"&gt;# Start n8n as a service&lt;/span&gt;
pm2 start n8n &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"n8n-automation"&lt;/span&gt;

&lt;span class="c"&gt;# Set up auto-start on boot&lt;/span&gt;
pm2 startup
pm2 save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Auto-restart on crashes&lt;/li&gt;
&lt;li&gt;Survives system reboots&lt;/li&gt;
&lt;li&gt;Runs independently of user sessions&lt;/li&gt;
&lt;li&gt;Built-in logging and monitoring&lt;/li&gt;
&lt;li&gt;No need for VSCode or browser to stay open&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Final Workflow
&lt;/h2&gt;

&lt;p&gt;Here’s what runs every morning at 9:15 AM:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Schedule Trigger&lt;/strong&gt; → Wakes up the workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gmail Node&lt;/strong&gt; → Fetches new emails from specific sender&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Node&lt;/strong&gt; → Extracts and cleans email content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summarization Chain&lt;/strong&gt; → AI-powered content analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP Request&lt;/strong&gt; → Creates formatted markdown in Obsidian&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;: Clean, formatted daily notes like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2025-07-29T14:30:00.000Z&lt;/span&gt;
&lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Financial Newsletter&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Email Summary&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Daily Email Summary - July 29, 2025&lt;/span&gt;

&lt;span class="gu"&gt;## Original Email Details&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**From**&lt;/span&gt;: Newsletter Name &lt;span class="nv"&gt;&amp;lt;sender@domain.com&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Subject**&lt;/span&gt;: Daily Market Analysis
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Date**&lt;/span&gt;: 2025-07-29T09:15:00.000Z

&lt;span class="gu"&gt;## AI Summary&lt;/span&gt;

&lt;span class="gs"&gt;**Top Stock Recommendations:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Company A (BUY) - Strong Q1 results
&lt;span class="p"&gt;-&lt;/span&gt; Company B (HOLD) - Mixed earnings outlook

&lt;span class="gs"&gt;**Market Insights:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Tech sector showing resilience
&lt;span class="p"&gt;-&lt;/span&gt; Energy stocks under pressure due to...
&lt;span class="p"&gt;
---&lt;/span&gt;
&lt;span class="ge"&gt;*Generated automatically at 14:30 IST*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Learnings
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modular approach&lt;/strong&gt;: Each step handles one responsibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart filtering&lt;/strong&gt;: Date-based filtering eliminates duplicate processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free AI tier&lt;/strong&gt;: Groq’s generous limits make this cost-effective&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local integration&lt;/strong&gt;: Direct file creation in knowledge management system&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Challenges Overcome&lt;/strong&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gmail API complexity&lt;/strong&gt;: Nested email structures require careful parsing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n8n HTTP limitations&lt;/strong&gt;: 204 response handling is currently buggy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production deployment&lt;/strong&gt;: Moving from development to 24/7 operation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content cleaning&lt;/strong&gt;: Raw email HTML needs significant processing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Future Improvements&lt;/strong&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple email sources&lt;/strong&gt;: Expand to other newsletter subscriptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content categorization&lt;/strong&gt;: Use AI to tag and organize summaries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trend analysis&lt;/strong&gt;: Weekly/monthly rollups of key themes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alert system&lt;/strong&gt;: Notify on high-priority market events&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost Breakdown
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Monthly Operating Costs&lt;/strong&gt;: ~$0&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n8n: Free (self-hosted)&lt;/li&gt;
&lt;li&gt;Gmail API: Free tier sufficient&lt;/li&gt;
&lt;li&gt;Groq AI: Free tier (14,400 requests/day)&lt;/li&gt;
&lt;li&gt;Obsidian: Local storage&lt;/li&gt;
&lt;li&gt;Mac Mini: Already owned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time Investment&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initial setup: ~4 hours&lt;/li&gt;
&lt;li&gt;Maintenance: ~5 minutes/month&lt;/li&gt;
&lt;li&gt;Daily time saved: ~15 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ROI&lt;/strong&gt;: After 2 weeks, the automation pays for itself in time savings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Security&lt;/strong&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;API keys stored in n8n’s encrypted credential system&lt;/li&gt;
&lt;li&gt;Local-only processing (no cloud data exposure)&lt;/li&gt;
&lt;li&gt;HTTPS with certificate validation for all external calls&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Reliability&lt;/strong&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;PM2 ensures 99%+ uptime&lt;/li&gt;
&lt;li&gt;Error handling for network issues&lt;/li&gt;
&lt;li&gt;Graceful degradation when services are unavailable&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Scalability&lt;/strong&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy to add new email sources&lt;/li&gt;
&lt;li&gt;AI processing handles variable content lengths&lt;/li&gt;
&lt;li&gt;File system can grow indefinitely&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building this automation transformed my morning routine. Instead of manually reading through lengthy financial newsletters, I now get concise, AI-generated summaries delivered directly to my knowledge management system.&lt;/p&gt;

&lt;p&gt;The technical journey revealed interesting challenges around email parsing, AI prompt engineering, and n8n’s HTTP handling limitations. But the end result is a robust, autonomous system that saves significant time daily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total setup time&lt;/strong&gt;: 4 hours&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Daily time saved&lt;/strong&gt;: 15 minutes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monthly maintenance&lt;/strong&gt;: 5 minutes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technical satisfaction&lt;/strong&gt;: Immeasurable 😊&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;If you’re inspired to build something similar:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start simple&lt;/strong&gt;: Begin with one email source and basic summarization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test thoroughly&lt;/strong&gt;: Run manually several times before automating&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle edge cases&lt;/strong&gt;: Empty emails, API failures, network issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor initially&lt;/strong&gt;: Watch logs for the first week to catch issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iterate&lt;/strong&gt;: Add features gradually based on actual usage&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The combination of n8n’s visual workflow builder, modern AI APIs, and local knowledge management creates powerful possibilities for personal automation.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you built similar automation workflows? What challenges did you face and how did you solve them? Share your experiences in the comments below!&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Engineering Leader with a decade of experience building scalable frontend architectures for high-traffic applications. Specialized in headless CMS implementations, performance optimization, and developer experience tooling. Currently architecting content delivery systems that serve millions of users while maintaining exceptional developer productivity.&lt;/p&gt;

&lt;p&gt;Passionate about sharing real-world engineering lessons learned from production deployments, code reviews, and the inevitable 2 AM debugging sessions that teach us the most.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect with me:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn&lt;/strong&gt;: &lt;a href="https://www.linkedin.com/in/stanleyjnadar/" rel="noopener noreferrer"&gt;linkedin.com/in/stanley-j&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Twitter&lt;/strong&gt;: &lt;a href="https://x.com/istealersn_dev" rel="noopener noreferrer"&gt;@istealersn_dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Substack&lt;/strong&gt;: &lt;a href="https://substack.com/@istealersn" rel="noopener noreferrer"&gt;@iStealersn.SubStack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Follow for more insights on frontend architecture, headless CMS patterns, and battle-tested engineering practices that actually work in production.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Have an optimization story or trick that worked wonders?&lt;/strong&gt; Drop it in the comments or tag me on your platform of choice. Let’s keep learning from each other.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tooling</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Less Javascript. More Performance - Have you wondered ever on this topic? Just posted my thoughts on how Astro can help you achieve that in a true sense</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Wed, 09 Jul 2025 12:59:21 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/less-javascript-more-performance-have-you-wondered-ever-on-this-topic-just-posted-my-thoughts-10if</link>
      <guid>https://dev.to/istealersn_dev/less-javascript-more-performance-have-you-wondered-ever-on-this-topic-just-posted-my-thoughts-10if</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/istealersn_dev/why-modern-websites-are-going-javascript-lite-22le" class="crayons-story__hidden-navigation-link"&gt;Why Modern Websites Are Going JavaScript-Lite&lt;/a&gt;


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

          &lt;a href="/istealersn_dev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" alt="istealersn_dev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/istealersn_dev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Stanley J
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Stanley J
                
              
              &lt;div id="story-author-preview-content-2671756" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/istealersn_dev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Stanley J&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/istealersn_dev/why-modern-websites-are-going-javascript-lite-22le" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 9 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/istealersn_dev/why-modern-websites-are-going-javascript-lite-22le" id="article-link-2671756"&gt;
          Why Modern Websites Are Going JavaScript-Lite
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/performance"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;performance&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/astro"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;astro&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/istealersn_dev/why-modern-websites-are-going-javascript-lite-22le#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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

&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
      <category>astro</category>
    </item>
    <item>
      <title>Why Modern Websites Are Going JavaScript-Lite</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Wed, 09 Jul 2025 12:58:24 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/why-modern-websites-are-going-javascript-lite-22le</link>
      <guid>https://dev.to/istealersn_dev/why-modern-websites-are-going-javascript-lite-22le</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Exploring Astro, Islands Architecture, and the Future of Static Site Generation&lt;/strong&gt;
&lt;/h3&gt;




&lt;p&gt;You know that moment when you open a “modern” website and your CPU fans spin up like you’re rendering a Pixar movie? Yeah, we’ve all been there. It’s 2025, and ironically, we’re using more JavaScript than ever—on sites that mostly display static content. The result? Bloated bundles, delayed interactivity, and a performance tax your users never signed up for.&lt;/p&gt;

&lt;p&gt;We’ve all seen it—shipping a blog redesign or a marketing site that looks perfect locally, only to run a Lighthouse report and realize it’s loading 500KB of JavaScript just to render static text. It’s a common reality when using tools like Next.js or Nuxt for content that doesn’t need to be interactive by default.&lt;/p&gt;

&lt;p&gt;The good news? A quiet revolution is brewing. And leading the charge are frameworks like &lt;strong&gt;Astro&lt;/strong&gt;, armed with concepts like &lt;strong&gt;Islands Architecture&lt;/strong&gt; and &lt;strong&gt;partial hydration&lt;/strong&gt;. These tools are helping us build faster, lighter, and more user-friendly web experiences.&lt;/p&gt;

&lt;p&gt;Let’s dig into why going JavaScript-lite isn’t just a trend—it’s becoming a smarter way to build for the web.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem: Heavy JavaScript for Light Use Cases&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Many modern frameworks ship a significant amount of JavaScript even when the content could be fully static. Consider a CMS-powered marketing site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;90% of it is static text and images&lt;/li&gt;
&lt;li&gt;Maybe one or two interactive elements&lt;/li&gt;
&lt;li&gt;Yet it still loads &lt;strong&gt;300–600KB of JS&lt;/strong&gt;, often parsed and executed upfront&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users don’t care whether you’re using SSR or CSR—they care that the content loads fast and feels instant.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Happens&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Traditional SPAs hydrate the entire DOM, even if only a few elements are interactive&lt;/li&gt;
&lt;li&gt;Frameworks prioritize developer DX over user experience by default&lt;/li&gt;
&lt;li&gt;Modern JS is powerful—but often overused&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real Talk:&lt;/strong&gt; Using a full JavaScript framework just to render static content is like bringing a tank to a paintball match.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;So What’s the Solution? Enter Astro — HTML First, JavaScript Optional&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When developers first try Astro, it can feel strange. Components aren’t interactive by default. There’s no massive client-side JavaScript bundle waiting to execute. But once you inspect the network tab and see how little gets shipped—it’s eye-opening.&lt;/p&gt;

&lt;p&gt;Astro flips the script. Instead of assuming everything needs hydration, it assumes &lt;strong&gt;nothing does&lt;/strong&gt;—unless you explicitly say so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MyButton&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/MyButton.astro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to My Blog&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is rendered 100% static.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyButton&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what’s going on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;h1&gt; and &lt;/h1&gt;
&lt;p&gt; get rendered to static HTML at build time&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;The  component is hydrated &lt;strong&gt;only&lt;/strong&gt; on the client&lt;/li&gt;
&lt;li&gt;No client-side JS gets shipped unless you opt-in&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What You Get:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tiny bundle sizes (20–40KB baseline for entire pages)&lt;/li&gt;
&lt;li&gt;Blazing fast initial paint times&lt;/li&gt;
&lt;li&gt;Better SEO, better accessibility, better developer karma&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Astro’s philosophy is best summed up by their tagline: &lt;strong&gt;“Ship less JavaScript.”&lt;/strong&gt; And once teams experience it, it’s hard to go back.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Let’s Talk Numbers: Bundle Analysis That Actually Matters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You can’t improve what you don’t measure. Most developers are surprised when they first run webpack-bundle-analyzer. Just including React and React-DOM often adds &lt;strong&gt;142KB gzipped&lt;/strong&gt;—before accounting for UI libraries, polyfills, or date utilities like moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step-by-step: Analyzing Your JavaScript Payload&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; webpack-bundle-analyzer
npx webpack &lt;span class="nt"&gt;--profile&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; stats.json
npx webpack-bundle-analyzer stats.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the resulting graph, you’ll likely see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;react-dom and react&lt;/li&gt;
&lt;li&gt;Repeated packages (like multiple versions of lodash)&lt;/li&gt;
&lt;li&gt;Components bundled that aren’t even used above the fold&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When teams switch to Astro, this often changes dramatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Astro default page: ~8KB JS (only interactive components)&lt;/li&gt;
&lt;li&gt;No hydration for static text/images&lt;/li&gt;
&lt;li&gt;Most pages ship &lt;strong&gt;0KB&lt;/strong&gt; of JS until interaction occurs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Code Splitting with Islands&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Islands architecture encourages natural code splitting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each island is an isolated entry point&lt;/li&gt;
&lt;li&gt;They hydrate only when needed&lt;/li&gt;
&lt;li&gt;JS is shipped based on what the user actually interacts with
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;idle&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NewsletterSignup&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;visible&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This design means smaller payloads and more effective tree shaking. Astro leverages Vite under the hood, which further optimizes unused exports.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Pro Tip:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use Vite’s visualizer plugin to examine your bundles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; rollup-plugin-visualizer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add to vite.config.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;visualizer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-visualizer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;visualizer&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Now Here’s Where It Gets Interesting: Islands Architecture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;… &lt;em&gt;(Unchanged content retained here for brevity)&lt;/em&gt; …&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Performance Story: Core Web Vitals That Actually Improve&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The real payoff of Astro and Islands isn’t just theoretical — production case studies reveal significant performance boosts.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Common Improvements:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Largest Contentful Paint (LCP)&lt;/strong&gt;: 2.6s → 1.1s&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First Input Delay (FID)&lt;/strong&gt;: 150ms → 21ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt;: Nearly zero&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These improvements stem from reduced JavaScript, smarter hydration, and static-first rendering.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example Lighthouse Scores:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance: 62&lt;/li&gt;
&lt;li&gt;LCP: 2.6s&lt;/li&gt;
&lt;li&gt;FID: 180ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance: 95&lt;/li&gt;
&lt;li&gt;LCP: 1.1s&lt;/li&gt;
&lt;li&gt;FID: 21ms&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Mobile-First Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;On slower devices, reduced JS leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less CPU usage&lt;/li&gt;
&lt;li&gt;Shorter time-to-interactive&lt;/li&gt;
&lt;li&gt;Better user perception of speed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Astro Patterns for Performance&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"hero.jpg 1x, hero@2x.jpg 2x"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Hero"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url('critical.css')&lt;/span&gt; &lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Measuring the Impact&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use both lab and field tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Synthetic testing&lt;/strong&gt;: Lighthouse, WebPageTest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RUM&lt;/strong&gt;: Vercel Analytics, Calibre, custom web-vitals logging&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Islands in the Wild: Advanced Patterns &amp;amp; Gotchas&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once you start building interactive features using islands, new architectural patterns emerge.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Sharing State Between Islands&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Without global state, communication between components may involve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON-encoded props&lt;/li&gt;
&lt;li&gt;localStorage/sessionStorage&lt;/li&gt;
&lt;li&gt;Custom DOM events
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Island A&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart:update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="c1"&gt;// Island B&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart:update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Dealing with Failed Hydration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use error boundaries to prevent blank UUI states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ErrorBoundary&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Something went wrong!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PriceChart&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ErrorBoundary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Signs You’re Over-Islanding&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Dozens of small hydrated components&lt;/li&gt;
&lt;li&gt;Performance regressions due to excessive inter-island sync&lt;/li&gt;
&lt;li&gt;Components relying on shared router/state libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Debugging Tips&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use astro dev --verbose and Chrome’s performance tools to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Profile hydration cost&lt;/li&gt;
&lt;li&gt;Identify waterfall delays in JavaScript execution&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Making the Switch: Migration Strategies That Actually Work&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Many teams migrating CMS-based or content-heavy websites to Astro start incrementally.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Recommended Migration Strategy&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Start with low-risk pages (e.g., homepage, about, blog)&lt;/li&gt;
&lt;li&gt;Keep interactive features wrapped in React/Vue components using Astro’s directives&lt;/li&gt;
&lt;li&gt;Refactor static content into .astro components&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Compatibility Example&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;From React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CTA.jsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CTA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To Astro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CTA&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/CTA.jsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CTA&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;idle&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Team Enablement Tips&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Share performance reports from Lighthouse audits&lt;/li&gt;
&lt;li&gt;Highlight familiar tooling support (React, Vue, Tailwind)&lt;/li&gt;
&lt;li&gt;Encourage 1–2 day spikes for learning Astro’s mental model&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Pitfalls to Avoid&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Import path mismatches&lt;/li&gt;
&lt;li&gt;Not specifying hydration directives&lt;/li&gt;
&lt;li&gt;Assumptions about global routing/state&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping It Up: We’re Not Going Back&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;JavaScript isn’t the problem—it’s how it’s been applied. When most of your site doesn’t need hydration, frameworks like Astro help you deliver what matters most: content, fast.&lt;/p&gt;

&lt;p&gt;Astro and Islands architecture provide a lightweight, flexible way to build high-performance, modern web experiences—without abandoning component-driven development.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Try This Next&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Audit your bundle with webpack-bundle-analyzer&lt;/li&gt;
&lt;li&gt;Migrate a single static page to Astro&lt;/li&gt;
&lt;li&gt;Experiment with client:visible and client:idle directives&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Your Turn&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Have you worked on performance optimizations or tried Astro? What worked well—or didn’t? Drop a comment, DM, or share your experience on LinkedIn or Twitter. Let’s learn together.&lt;/p&gt;




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

&lt;p&gt;Engineering Leader with a decade of experience building scalable frontend architectures for high-traffic applications. Specialized in headless CMS implementations, performance optimization, and developer experience tooling. Currently architecting content delivery systems that serve millions of users while maintaining exceptional developer productivity.&lt;/p&gt;

&lt;p&gt;Passionate about sharing real-world engineering lessons learned from production deployments, code reviews, and the inevitable 2 AM debugging sessions that teach us the most.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect with me:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn&lt;/strong&gt;: &lt;a href="https://www.linkedin.com/in/stanleyjnadar/" rel="noopener noreferrer"&gt;linkedin.com/in/stanley-j&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Twitter&lt;/strong&gt;: &lt;a href="https://x.com/istealersn_dev" rel="noopener noreferrer"&gt;@istealersn_dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iStealerSn Substack&lt;/strong&gt;: &lt;a href="https://istealersn.substack.com/" rel="noopener noreferrer"&gt;istealersn.substack.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Follow for more insights on frontend architecture, headless CMS patterns, and battle-tested engineering practices that actually work in production.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
      <category>astro</category>
    </item>
    <item>
      <title>Ever stared at a red Lighthouse score wondering "didn't we just optimize this last sprint?" - No fluff. Just the techniques that make your sites snappier and users happier.</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Wed, 02 Jul 2025 06:18:09 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/ever-stared-at-a-red-lighthouse-score-wondering-didnt-we-just-optimize-this-last-sprint-no-49fm</link>
      <guid>https://dev.to/istealersn_dev/ever-stared-at-a-red-lighthouse-score-wondering-didnt-we-just-optimize-this-last-sprint-no-49fm</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/istealersn_dev/a-developers-guide-to-faster-page-rendering-5bg9" class="crayons-story__hidden-navigation-link"&gt;A Developer's Guide to Faster Page Rendering&lt;/a&gt;


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

          &lt;a href="/istealersn_dev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" alt="istealersn_dev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/istealersn_dev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Stanley J
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Stanley J
                
              
              &lt;div id="story-author-preview-content-2646193" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/istealersn_dev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Stanley J&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/istealersn_dev/a-developers-guide-to-faster-page-rendering-5bg9" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 2 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/istealersn_dev/a-developers-guide-to-faster-page-rendering-5bg9" id="article-link-2646193"&gt;
          A Developer's Guide to Faster Page Rendering
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webperf"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webperf&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/istealersn_dev/a-developers-guide-to-faster-page-rendering-5bg9" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/istealersn_dev/a-developers-guide-to-faster-page-rendering-5bg9#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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

&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>webperf</category>
      <category>programming</category>
    </item>
    <item>
      <title>A Developer's Guide to Faster Page Rendering</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Wed, 02 Jul 2025 06:17:15 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/a-developers-guide-to-faster-page-rendering-5bg9</link>
      <guid>https://dev.to/istealersn_dev/a-developers-guide-to-faster-page-rendering-5bg9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: We've All Been There
&lt;/h2&gt;

&lt;p&gt;You're sipping your third cup of coffee at 11 AM, staring at a CMS-powered website that takes &lt;em&gt;forever&lt;/em&gt; to load. You hit the Lighthouse tab, and it's redder than a rage tweet. You're wondering: &lt;em&gt;"Didn't we just optimize this last sprint?"&lt;/em&gt; Sound familiar?&lt;/p&gt;

&lt;p&gt;If you've ever worked with CMS platforms—headless or traditional—you know that performance bottlenecks can sneak up like a rogue &lt;code&gt;console.log&lt;/code&gt; in production. In this post, we're going to break down real-world performance strategies for speeding up both your website and the CMS backend that powers it.&lt;/p&gt;

&lt;p&gt;No fluff. Just the stuff that makes your site snappier, your pages faster, and your users happier.&lt;/p&gt;

&lt;p&gt;Here’s what we’ll unpack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where CMS performance usually breaks down&lt;/li&gt;
&lt;li&gt;What frontend optimizations move the needle&lt;/li&gt;
&lt;li&gt;CMS-specific tricks (template tuning, caching, CDNs—you name it)&lt;/li&gt;
&lt;li&gt;How to actually measure what matters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let’s dive in, developer-to-developer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Performance Bottlenecks in CMS Environments
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Database Query Nightmares (Hello, N+1)
&lt;/h3&gt;

&lt;p&gt;CMSs often abstract database queries, but that abstraction can be sneaky. You end up with an N+1 query issue faster than you can say &lt;code&gt;await Promise.all()&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: You loop through 100 blog posts and fetch their author names inside the loop. Boom. 101 queries instead of 2.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Fix it with:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Use eager loading or batched queries&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postsWithAuthors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Pro Tip: Use query logs to track query count. Prisma, Sequelize, and even WordPress with Query Monitor can help you debug this fast.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Asset Loading &amp;amp; Bundling Chaos
&lt;/h3&gt;

&lt;p&gt;You know what kills Time to Interactive (TTI)? A bloated JavaScript bundle and unoptimized CSS that ships everything to everyone.&lt;/p&gt;

&lt;p&gt;Bundle size matters—don’t @ me.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSR vs CSR: It’s Complicated
&lt;/h3&gt;

&lt;p&gt;Server-Side Rendering (SSR) gives you better initial paint, but it can introduce backend pressure. Client-Side Rendering (CSR) feels like a React hangover when JS fails to load. Choose wisely.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reality check: Sometimes, the fastest page is the one that doesn’t need JavaScript at all. Static rendering FTW.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Plugin Overload: CMS Bloatware
&lt;/h3&gt;

&lt;p&gt;Raise your hand if you’ve inherited a CMS with 27 plugins and you only know what 3 of them do. &lt;/p&gt;

&lt;p&gt;Each plugin might add its own scripts, database queries, or templates. That’s a recipe for slowness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Action step:&lt;/strong&gt; Audit those plugins. Disable or remove anything non-critical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache Invalidation: The Silent Killer
&lt;/h3&gt;

&lt;p&gt;"It works on my machine"—because your cache didn’t expire. Poor cache strategies mean either stale content or unnecessary re-renders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Version your assets. Cache intelligently. Invalidate surgically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frontend Optimization Strategies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Critical CSS &amp;amp; Above-the-Fold Love
&lt;/h3&gt;

&lt;p&gt;Load what the user sees first. Defer the rest. It’s like serving the best part of the burger first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* Extracted Critical CSS */&lt;/span&gt;
  &lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.hero-title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"main.css"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"style"&lt;/span&gt; &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"this.rel='stylesheet'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tools: Critical, Next.js' styled-jsx, or manual extraction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  JavaScript Bundling &amp;amp; Code Splitting
&lt;/h3&gt;

&lt;p&gt;Don't serve your admin dashboard logic to the homepage. Code split by route and component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dynamic import&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PostDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./PostDetails&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tooling: Webpack, Vite, or esbuild—just don’t ignore your bundle-analyzer reports.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Image Optimization: Lazy All the Way
&lt;/h3&gt;

&lt;p&gt;Images are the heaviest resource you ship. Compress, resize, and lazy-load.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"hero.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Welcome"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Bonus: Use AVIF or WebP for modern browsers. For browsers that don’t support these formats, provide JPEG or PNG fallbacks using the  element. Also, consider using srcset and sizes attributes to serve appropriately sized images based on device viewport for responsive performance gains.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Web Fonts: The Hidden Lag
&lt;/h3&gt;

&lt;p&gt;Ever seen that flash of invisible text (FOIT)? That’s your font dragging its feet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"fonts/inter.woff2"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"font"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"font/woff2"&lt;/span&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Pro Tip: Self-host fonts. Limit to 2–3 weights. Fallback to system fonts when possible. Use font-display: swap to prevent FOIT and improve perceived performance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  PWA Goodies (That You’ll Actually Use)
&lt;/h3&gt;

&lt;p&gt;Progressive Web Apps aren't just a buzzword. Service Workers can cache assets and speed up return visits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Simplified example for demo purposes&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// In production, be sure to add error handling and use versioned caches for reliability.&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;When not to use: If your CMS content changes frequently, stale cache can backfire.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  CMS-Specific Optimization Techniques
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Content Delivery &amp;amp; Smart Caching
&lt;/h3&gt;

&lt;p&gt;Caching is king—but the rules are different per CMS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WordPress:&lt;/strong&gt; Use plugins like W3 Total Cache or WP Rocket.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Headless:&lt;/strong&gt; Rely on CDN edge caches (like Vercel or Cloudflare).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;CDN Rule of Thumb: Cache HTML cautiously, static assets aggressively.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Template Optimization
&lt;/h3&gt;

&lt;p&gt;Nunjucks, Twig, Liquid—you name it. Templates can choke performance if they loop excessively or make nested queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do this:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memoize repeated blocks&lt;/li&gt;
&lt;li&gt;Cache partials where possible&lt;/li&gt;
&lt;li&gt;Avoid inline DB calls&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dynamic Queries Done Right
&lt;/h3&gt;

&lt;p&gt;CMSs often let you inject logic into templates. That’s where you can optimize or crash performance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use batched or parameterized queries in middleware or API routes—not templates.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Next.js API route example&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getPosts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  CDN Integration Patterns
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Serve static assets from CDN (images, scripts, fonts)&lt;/li&gt;
&lt;li&gt;Use cache headers (&lt;code&gt;Cache-Control&lt;/code&gt;, &lt;code&gt;ETag&lt;/code&gt;, &lt;code&gt;Surrogate-Control&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Purge intelligently using webhook triggers on publish&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Headless vs Traditional CMS: Speed Showdown
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Headless CMS&lt;/th&gt;
&lt;th&gt;Traditional CMS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSR Ready&lt;/td&gt;
&lt;td&gt;Yes (Next.js, Nuxt)&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CDN Integration&lt;/td&gt;
&lt;td&gt;Seamless&lt;/td&gt;
&lt;td&gt;Often requires plugins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance Control&lt;/td&gt;
&lt;td&gt;You own it&lt;/td&gt;
&lt;td&gt;Shared with CMS core&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Rule of Thumb: Go headless if you want performance control. Stick with traditional if you need speed-to-launch.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Monitoring and Measurement
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tools That Actually Help
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core Web Vitals&lt;/strong&gt; (LCP, FID, CLS) for Google ranking and UX benchmarks &lt;strong&gt;Lighthouse&lt;/strong&gt; for quick audits&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebPageTest&lt;/strong&gt; for deep dives&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New Relic / Datadog&lt;/strong&gt; for backend tracing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sentry&lt;/strong&gt; for JS performance monitoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Analytics (v4)&lt;/strong&gt; for behavior-based insights&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance Budgets
&lt;/h3&gt;

&lt;p&gt;Set them. Stick to them. Or your page weight will balloon faster than a feature backlog.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"performanceBudget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"firstContentfulPaint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"maxBundleSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"imageWeight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;These&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;baseline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;values;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;adjust&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;based&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;site's&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;demographics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;performance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;goals&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  RUM vs Synthetic Testing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RUM (Real User Monitoring):&lt;/strong&gt; Real-world, diverse devices and networks. Great for catching edge cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synthetic Testing:&lt;/strong&gt; Lab-based, controlled, repeatable. Great for regressions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use both.&lt;/strong&gt; They complement each other like TypeScript and... well, TypeScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up: Make Your Site Fly, Not Crawl
&lt;/h2&gt;

&lt;p&gt;Website and CMS performance isn't just a Lighthouse score—it's user experience, retention, and even SEO. The good news? You’ve got the tools and techniques to fight back.&lt;/p&gt;

&lt;p&gt;From trimming down your JS bundles to slapping lazy-load on your images and getting smart with caching, every small gain adds up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next Steps:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Run a Lighthouse audit on your current site&lt;/li&gt;
&lt;li&gt;Pick 2–3 low-hanging fruits to optimize&lt;/li&gt;
&lt;li&gt;Set a performance budget&lt;/li&gt;
&lt;li&gt;Share your results with your team (and maybe us!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s make the web faster—one CMS at a time. 🚀&lt;/p&gt;




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

&lt;p&gt;Engineering Leader with a decade of experience building scalable frontend architectures for high-traffic applications. Specialized in headless CMS implementations, performance optimization, and developer experience tooling. Currently architecting content delivery systems that serve millions of users while maintaining exceptional developer productivity.&lt;/p&gt;

&lt;p&gt;Passionate about sharing real-world engineering lessons learned from production deployments, code reviews, and the inevitable 2 AM debugging sessions that teach us the most.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect with me:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn&lt;/strong&gt;: &lt;a href="https://www.linkedin.com/in/stanleyjnadar/" rel="noopener noreferrer"&gt;linkedin.com/in/stanley-j&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Twitter&lt;/strong&gt;: &lt;a href="https://x.com/istealersn_dev" rel="noopener noreferrer"&gt;@istealersn_dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Substack&lt;/strong&gt;: &lt;a href="https://istealersn.substack.com/" rel="noopener noreferrer"&gt;istealersn.substack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Follow for more insights on frontend architecture, headless CMS patterns, and battle-tested engineering practices that actually work in production.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Have an optimization story or trick that worked wonders?&lt;/strong&gt; Drop it in the comments or tag me on your platform of choice. Let’s keep learning from each other.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>webperf</category>
      <category>programming</category>
    </item>
    <item>
      <title>Published a comprehensive guide on building headless CMS frontends that actually work in production. This isn't another "getting started" tutorial—it's the architectural decisions and real-world lessons learned from multiple implementations.</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Thu, 26 Jun 2025 11:32:49 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/just-published-a-comprehensive-guide-on-building-headless-cms-frontends-that-actually-work-in-51fm</link>
      <guid>https://dev.to/istealersn_dev/just-published-a-comprehensive-guide-on-building-headless-cms-frontends-that-actually-work-in-51fm</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc" class="crayons-story__hidden-navigation-link"&gt;Architecting a Headless CMS Frontend: Principles, Patterns, and Pitfalls&lt;/a&gt;


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

          &lt;a href="/istealersn_dev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" alt="istealersn_dev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/istealersn_dev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Stanley J
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Stanley J
                
              
              &lt;div id="story-author-preview-content-2620614" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/istealersn_dev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Stanley J&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 24 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc" id="article-link-2620614"&gt;
          Architecting a Headless CMS Frontend: Principles, Patterns, and Pitfalls
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/api"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;api&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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

&lt;/div&gt;


</description>
      <category>api</category>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How have you approached your strategy to setup headless CMS?</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Wed, 25 Jun 2025 02:49:51 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/how-have-you-approached-your-strategy-to-setup-headless-cms-3n24</link>
      <guid>https://dev.to/istealersn_dev/how-have-you-approached-your-strategy-to-setup-headless-cms-3n24</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc" class="crayons-story__hidden-navigation-link"&gt;Architecting a Headless CMS Frontend: Principles, Patterns, and Pitfalls&lt;/a&gt;


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

          &lt;a href="/istealersn_dev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" alt="istealersn_dev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/istealersn_dev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Stanley J
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Stanley J
                
              
              &lt;div id="story-author-preview-content-2620614" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/istealersn_dev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Stanley J&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 24 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc" id="article-link-2620614"&gt;
          Architecting a Headless CMS Frontend: Principles, Patterns, and Pitfalls
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/api"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;api&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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

&lt;/div&gt;


</description>
      <category>api</category>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Just shipped a deep dive on headless CMS frontend architecture. Biggest takeaway while writing this? Your technical architecture can be perfect, but if content authors don't trust the preview functionality, the whole thing falls apart. Share your thoughts!</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Tue, 24 Jun 2025 10:05:50 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/just-shipped-a-deep-dive-on-headless-cms-frontend-architecture-biggest-takeaway-while-writing-264</link>
      <guid>https://dev.to/istealersn_dev/just-shipped-a-deep-dive-on-headless-cms-frontend-architecture-biggest-takeaway-while-writing-264</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/istealersn_dev" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" alt="istealersn_dev"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Architecting a Headless CMS Frontend: Principles, Patterns, and Pitfalls&lt;/h2&gt;
      &lt;h3&gt;Stanley J ・ Jun 24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#api&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>api</category>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Architecting a Headless CMS Frontend: Principles, Patterns, and Pitfalls</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Tue, 24 Jun 2025 10:02:27 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc</link>
      <guid>https://dev.to/istealersn_dev/architecting-a-headless-cms-frontend-principles-patterns-and-pitfalls-42gc</guid>
      <description>&lt;p&gt;After implementing headless CMS architectures across multiple production systems, I've learned that success hinges on understanding three core patterns and avoiding five common pitfalls. This isn't about whether you should go headless—it's about doing it right when you do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Teams Choose Headless (And Why It Matters)
&lt;/h2&gt;

&lt;p&gt;Headless CMS architectures decouple content management from presentation, exposing content via APIs rather than rendering pages server-side. We see teams adopting this approach for three main reasons: multi-channel content delivery becomes trivial, performance improves dramatically through static generation and edge caching, and developer velocity increases when frontend teams can iterate independently.&lt;/p&gt;

&lt;p&gt;The fundamental shift is architectural: content becomes data, not markup. This enables powerful patterns like content reuse across touch points, programmatic content manipulation, and sophisticated caching strategies that traditional CMS platforms struggle with.&lt;/p&gt;

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

&lt;p&gt;The key insight is that your &lt;strong&gt;mobile app&lt;/strong&gt;, &lt;strong&gt;frontend website&lt;/strong&gt;, and &lt;strong&gt;third-party integrations&lt;/strong&gt; all use the &lt;strong&gt;same content APIs&lt;/strong&gt;. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single source of truth&lt;/strong&gt; for all content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent data structure&lt;/strong&gt; across all touch points&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced maintenance&lt;/strong&gt; - one API to rule them all&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future-proof&lt;/strong&gt; - new integrations use existing APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Real-World Example:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine an e-commerce company where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend website&lt;/strong&gt; displays product pages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile app&lt;/strong&gt; shows the same products&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email marketing&lt;/strong&gt; pulls product descriptions for campaigns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics dashboard&lt;/strong&gt; tracks content performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer support&lt;/strong&gt; accesses product specs for help tickets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these systems hit the same headless CMS APIs, ensuring consistency and reducing the integration burden.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the core value proposition of headless CMS&lt;/strong&gt;: write content once, distribute everywhere through APIs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Core Architecture Patterns That Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pattern 1: Hybrid Rendering Strategy
&lt;/h3&gt;

&lt;p&gt;Don't choose between static and dynamic—use both strategically. Different content types have different requirements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Match rendering strategy to content characteristics&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getRevalidationStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;strategies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;marketing-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// 24 hours - rarely changes&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blog-post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// 1 hour - occasional updates&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;product-info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// 30 minutes - price changes&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;news&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="c1"&gt;// 5 minutes - breaking updates&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The key insight: &lt;strong&gt;content update frequency should drive your caching strategy&lt;/strong&gt;, not technology preferences. Marketing pages can be static for days, while product prices need frequent updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 2: Type-Safe Content Contracts
&lt;/h3&gt;

&lt;p&gt;Runtime validation prevents malformed content from breaking your application. The architecture pattern is validation at the boundary, not throughout your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Validate once at the API boundary&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ContentSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cta&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;publishedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iso&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Your app works with validated types everywhere else&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ContentSchema&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Architectural decision&lt;/strong&gt;: Fail fast at the data boundary rather than handling invalid content throughout your component tree.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 3: Component-Driven Content Architecture
&lt;/h3&gt;

&lt;p&gt;Map CMS content blocks to React components for flexible page building. The pattern is about &lt;strong&gt;separation of concerns&lt;/strong&gt;—content structure drives component selection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Content drives component selection&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;componentMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HeroComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TextBlock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImageBlock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CallToAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderContentBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ContentBlock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;componentMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key architectural insight&lt;/strong&gt;: Let content authors compose pages by selecting component types, not by writing HTML or choosing layouts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Five Common Pitfalls (And How to Avoid Them)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Vendor Lock-in Through Proprietary APIs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: CMS vendors provide convenient SDKs that create subtle dependencies on their specific implementations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: Abstract CMS interactions behind your own interfaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create vendor-agnostic contracts&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ContentRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ContentBlock&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;searchContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ContentBlock&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Implementation can be swapped without changing your app&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContentfulRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ContentRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetchContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ContentBlock&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transformToContentBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Architectural insight&lt;/strong&gt;: The repository pattern isn't just good practice—it's insurance against vendor changes and migration nightmares.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Overfetching Without Realizing It
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: GraphQL doesn't automatically prevent overfetching—poorly designed queries can request unnecessary data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: Design component-specific fragments, not kitchen-sink queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad: Everything for everyone&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;KITCHEN_SINK_QUERY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query GetPost($id: ID!) {
    post(id: $id) {
      title content author { name bio avatar socialLinks }
      seo { title description keywords }
      analytics { views shares }
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Good: Component-specific needs&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POST_SUMMARY_FRAGMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  fragment PostSummary on Post {
    title excerpt publishedAt
    author { name avatar }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key decision&lt;/strong&gt;: Optimize for component requirements, not data availability.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ignoring Content Author Experience
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: Technical teams focus on developer experience and forget that content authors need to use the system daily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: Treat preview functionality as a first-class feature, not an afterthought.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Preview mode should be reliable, not fragile&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generatePreviewData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;searchParams&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PREVIEW_SECRET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Always fetch fresh content for previews&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchDraftContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/preview/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical insight&lt;/strong&gt;: If content authors can't trust preview mode, they'll stop using your headless system.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Underestimating Build Time Impact
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: Static generation sounds great until your build times hit 20+ minutes and block deployments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: Implement on-demand revalidation instead of rebuilding everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Revalidate specific content, not entire site&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;contentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Surgical cache invalidation&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;revalidateTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`content-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contentId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;revalidated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;revalidated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Architectural decision&lt;/strong&gt;: Plan for content velocity from day one, not when builds start timing out.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Poor Error Boundaries for Content Failures
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: One malformed content block breaks the entire page, creating a terrible user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: Implement granular error boundaries around content components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Isolate content rendering failures&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ContentBlockErrorBoundary&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ErrorBoundary&lt;/span&gt;
      &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Log but don't crash the page&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content block failed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ErrorBoundary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical pattern&lt;/strong&gt;: Content failures should degrade gracefully, not cascade through your entire application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Content Deployment Pipeline
&lt;/h2&gt;

&lt;p&gt;Understanding the technical patterns is only half the battle. Successful headless CMS implementations require robust deployment workflows that content teams can trust. Here's the pipeline we've refined across multiple production deployments:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;A → B: Content Update → Webhook Trigger&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Content authors publish changes in the CMS, automatically triggering webhooks to your build system. This eliminates manual deployment steps and ensures content changes flow through your pipeline consistently.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;B → C: Webhook Trigger → Validation Check&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Validate incoming content before processing. Check for required fields, schema compliance, and content structure. This prevents malformed content from breaking your build process—a critical step that many teams skip until they get burned.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;C → D: Validation Check → Build Process&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If validation passes, trigger your build or regeneration process. The key architectural decision here: full rebuild vs. incremental updates based on content type and change scope.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;D → E: Build Process → Preview Deploy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Deploy to a staging environment first. This step is non-negotiable for content team confidence. If content authors can't reliably preview their changes, they'll lose trust in your headless system.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;E → F: Preview Deploy → Production Deploy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After preview approval, deploy to production. This can be automatic for low-risk content types or require manual approval for critical pages. Design this step based on your organization's risk tolerance.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;F → G: Production Deploy → Cache Invalidation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Clear CDN caches for updated content paths. The architectural challenge: invalidate only what changed to maintain performance while ensuring content freshness.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;G → H: Cache Invalidation → Performance Check&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Monitor Core Web Vitals and load times after deployment. This feedback loop catches performance regressions and validates that your caching strategy is working as intended.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pipeline insight&lt;/strong&gt;: Each step addresses a common failure point in headless implementations. The diagram shows why preview functionality and build time considerations—two of our biggest pitfalls—are architectural requirements, not nice-to-haves.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Successful headless CMS implementations come down to three core patterns: hybrid rendering strategies that match content characteristics, type-safe content contracts that prevent runtime failures, and component-driven architectures that enable flexible content creation.&lt;/p&gt;

&lt;p&gt;The biggest pitfalls aren't technical—they're organizational. Vendor lock-in, poor author experience, and inadequate error handling cause more headless CMS failures than architectural decisions. Plan for these human factors as carefully as you plan your component hierarchies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key insight&lt;/strong&gt;: Headless CMS success depends as much on content team workflows as technical architecture. The best pattern libraries in the world won't save you if your content authors can't effectively use the system.&lt;/p&gt;

&lt;p&gt;Start with solid foundations—runtime validation, error boundaries, and preview workflows—then optimize for performance. Your content team will thank you, and your architecture will scale gracefully as requirements evolve.&lt;/p&gt;




&lt;h2&gt;
  
  
  Additional References
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Headless CMS Platforms &amp;amp; Documentation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.contentful.com/developers/docs/" rel="noopener noreferrer"&gt;&lt;strong&gt;Contentful Documentation&lt;/strong&gt;&lt;/a&gt;: Comprehensive API documentation and best practices&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.strapi.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;Strapi Documentation&lt;/strong&gt;&lt;/a&gt;: Open-source headless CMS implementation guide&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.sanity.io/docs" rel="noopener noreferrer"&gt;&lt;strong&gt;Sanity Documentation&lt;/strong&gt;&lt;/a&gt;: Real-time collaborative editing and flexible content modeling&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/docs/basic-features/data-fetching" rel="noopener noreferrer"&gt;&lt;strong&gt;Next.js Data Fetching&lt;/strong&gt;&lt;/a&gt;: SSG, SSR, and ISR implementation patterns&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kit.svelte.dev/docs/load" rel="noopener noreferrer"&gt;&lt;strong&gt;SvelteKit Loading Data&lt;/strong&gt;&lt;/a&gt;: Svelte patterns for data fetching and rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Performance &amp;amp; Validation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;Zod Documentation&lt;/strong&gt;&lt;/a&gt;: Runtime schema validation for API responses&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;&lt;strong&gt;TanStack Query Documentation&lt;/strong&gt;&lt;/a&gt;: Advanced caching and data synchronization&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://web.dev/vitals/" rel="noopener noreferrer"&gt;&lt;strong&gt;Core Web Vitals Guide&lt;/strong&gt;&lt;/a&gt;: Performance metrics that matter for headless sites&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Engineering Leader with a decade of experience building scalable frontend architectures for high-traffic applications. Specialized in headless CMS implementations, performance optimization, and developer experience tooling. Currently architecting content delivery systems that serve millions of users while maintaining exceptional developer productivity.&lt;/p&gt;

&lt;p&gt;Passionate about sharing real-world engineering lessons learned from production deployments, code reviews, and the inevitable 2 AM debugging sessions that teach us the most.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Connect with me:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn&lt;/strong&gt;: &lt;a href="https://www.linkedin.com/in/stanleyjnadar/" rel="noopener noreferrer"&gt;linkedin.com/in/stanley-j&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Twitter&lt;/strong&gt;: &lt;a href="https://x.com/istealersn_dev" rel="noopener noreferrer"&gt;@istealersn_dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Substack: &lt;a href="https://substack.com/@istealersn" rel="noopener noreferrer"&gt;@istealersn Substack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Follow for more insights on frontend architecture, headless CMS patterns, and battle-tested engineering practices that actually work in production.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>api</category>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Any DIY projects you can relate to or wanna share here? I would love to read and also happy to receive feedback</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Wed, 18 Jun 2025 15:40:37 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/any-diy-projects-you-can-relate-to-or-wanna-share-here-i-would-love-to-read-and-also-happy-to-4766</link>
      <guid>https://dev.to/istealersn_dev/any-diy-projects-you-can-relate-to-or-wanna-share-here-i-would-love-to-read-and-also-happy-to-4766</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/istealersn_dev" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" alt="istealersn_dev"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/istealersn_dev/diy-icloud-photo-backup-with-album-structure-1dif" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;DIY iCloud Photo Backup (With Album Structure!)&lt;/h2&gt;
      &lt;h3&gt;Stanley J ・ Jun 17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#automation&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#applescript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>automation</category>
      <category>applescript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I Automated My Daily Workflow with macOS Automator - skip cloud storage fees</title>
      <dc:creator>Stanley J</dc:creator>
      <pubDate>Tue, 17 Jun 2025 09:14:22 +0000</pubDate>
      <link>https://dev.to/istealersn_dev/how-i-automated-my-daily-workflow-with-macos-automator-skip-cloud-storage-fees-28i3</link>
      <guid>https://dev.to/istealersn_dev/how-i-automated-my-daily-workflow-with-macos-automator-skip-cloud-storage-fees-28i3</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/istealersn_dev/diy-icloud-photo-backup-with-album-structure-1dif" class="crayons-story__hidden-navigation-link"&gt;DIY iCloud Photo Backup (With Album Structure!)&lt;/a&gt;


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

          &lt;a href="/istealersn_dev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" alt="istealersn_dev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/istealersn_dev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Stanley J
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Stanley J
                
              
              &lt;div id="story-author-preview-content-2599066" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/istealersn_dev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F891849%2Fae0669b3-2be7-4a8e-bcc3-35ac3f74dc7d.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Stanley J&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/istealersn_dev/diy-icloud-photo-backup-with-album-structure-1dif" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 17 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/istealersn_dev/diy-icloud-photo-backup-with-album-structure-1dif" id="article-link-2599066"&gt;
          DIY iCloud Photo Backup (With Album Structure!)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/automation"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;automation&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/applescript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;applescript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/beginners"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;beginners&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/istealersn_dev/diy-icloud-photo-backup-with-album-structure-1dif" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/istealersn_dev/diy-icloud-photo-backup-with-album-structure-1dif#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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

&lt;/div&gt;


</description>
      <category>automation</category>
      <category>applescript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
