<?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: lucas-brdt268</title>
    <description>The latest articles on DEV Community by lucas-brdt268 (@lucasbrdt268).</description>
    <link>https://dev.to/lucasbrdt268</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%2F3211487%2F5183a6ed-e062-4b2c-8ad5-91308262e264.png</url>
      <title>DEV Community: lucas-brdt268</title>
      <link>https://dev.to/lucasbrdt268</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucasbrdt268"/>
    <language>en</language>
    <item>
      <title>Headless Adventures: From CMS to Frontend Without Losing Your Mind (6)</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Wed, 19 Nov 2025 20:05:16 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-6-23i</link>
      <guid>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-6-23i</guid>
      <description>&lt;h2&gt;
  
  
  🤖 CI/CD for Content: Automating CMS Updates Without Deploying 20 Times a Day
&lt;/h2&gt;

&lt;p&gt;You know what’s fun?&lt;br&gt;
Developers pushing code.&lt;br&gt;
You know what’s &lt;em&gt;not&lt;/em&gt; fun?&lt;br&gt;
Marketing pushing CMS updates every 5 minutes like they’re speedrunning content creation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hey, the title didn’t show up yet. Can you redeploy?”&lt;br&gt;
“I fixed a typo.”&lt;br&gt;
“Can you redeploy again?”&lt;br&gt;
“Changed it back.”&lt;br&gt;
“One more deploy please 🙏”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At this point, you’re basically a human CI/CD pipeline.&lt;br&gt;
Let’s stop that.&lt;/p&gt;


&lt;h3&gt;
  
  
  🧠 Why CI/CD for Content Matters
&lt;/h3&gt;

&lt;p&gt;Modern headless CMS apps have 3 problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Editors move fast&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frontend needs the latest content&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developers want to sleep&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So instead of redeploying manually like it’s 2005, we automate content updates.&lt;br&gt;
Let the pipeline work while you enjoy your ramen 🍜.&lt;/p&gt;


&lt;h3&gt;
  
  
  🔥 Method 1: Webhooks Triggering Rebuilds (The Classic Move)
&lt;/h3&gt;

&lt;p&gt;Most headless CMSs (Strapi, Directus, Sanity, Payload, everything except Notepad.exe) allow you to send a webhook when content changes.&lt;/p&gt;

&lt;p&gt;So when an editor hits &lt;strong&gt;Publish&lt;/strong&gt;, your CMS fires a request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/rebuild-frontend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dockploy, Netlify, or Vercel sees that and says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Ah, new content. Time to work.” 🛠️💨&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Boom — automatic redeploy.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example (Strapi → Dockploy webhook)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;CMS event:&lt;/strong&gt; article created&lt;br&gt;
&lt;strong&gt;Webhook target:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://dockploy.app/hooks/frontend/redeploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your frontend updates instantly.&lt;br&gt;
Your editor smiles.&lt;br&gt;
You pretend you didn’t spend an entire afternoon setting it up.&lt;/p&gt;


&lt;h3&gt;
  
  
  ⚡ Method 2: Incremental Static Regeneration (ISR)
&lt;/h3&gt;

&lt;p&gt;(&lt;em&gt;a.k.a. “Lazy Deployment, Smart App”&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;If you’re using &lt;strong&gt;Next.js&lt;/strong&gt;, ISR is the chill cousin of SSG:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You deploy once&lt;/li&gt;
&lt;li&gt;Content regenerates on-demand&lt;/li&gt;
&lt;li&gt;No manual redeploys&lt;/li&gt;
&lt;li&gt;No webhook drama&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getStaticProps&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;data&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;fetchCMS&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// re-generate every minute&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes your app smarter than most of your meetings.&lt;br&gt;
It just &lt;em&gt;updates itself&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Your CMS team asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Can you redeploy?”&lt;br&gt;
You reply:&lt;br&gt;
“It auto-refreshes, my friend. You’re living in the future now.” ✨&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  🧨 Method 3: On-Demand Revalidation (Next.js 13+)
&lt;/h3&gt;

&lt;p&gt;CMS updates → your API endpoint → revalidate page.&lt;/p&gt;

&lt;p&gt;No full rebuild needed.&lt;br&gt;
No waiting.&lt;br&gt;
No crying.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&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="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;slug&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;req&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="nf"&gt;revalidatePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/blog/&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your frontend becomes so dynamic it should charge rent.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧪 Method 4: Polling
&lt;/h3&gt;

&lt;p&gt;(&lt;em&gt;a.k.a. The “Are We There Yet?” Strategy&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;If all else fails (small CMS, no webhooks), poll like a patient parent:&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="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchNewContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not elegant.&lt;br&gt;
Not fancy.&lt;br&gt;
But hey—&lt;br&gt;
it works. 😎&lt;/p&gt;




&lt;h3&gt;
  
  
  🛠️ Real-World Setup: Dockploy + Headless CMS + Next.js
&lt;/h3&gt;

&lt;p&gt;Here’s the “beautiful triangle” setup:&lt;/p&gt;

&lt;h4&gt;
  
  
  1️⃣ Your CMS → sends webhook on publish
&lt;/h4&gt;

&lt;p&gt;→ To a Dockploy redeploy endpoint&lt;br&gt;
→ Or to your Next.js revalidate endpoint&lt;/p&gt;

&lt;h4&gt;
  
  
  2️⃣ Your Dockploy app
&lt;/h4&gt;

&lt;p&gt;Builds fresh pages &lt;em&gt;automatically&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3️⃣ Your frontend
&lt;/h4&gt;

&lt;p&gt;Always stays up-to-date&lt;br&gt;
No manual deploys&lt;br&gt;
No “HELLLLP the content didn’t update” messages&lt;/p&gt;

&lt;p&gt;Developers: 🧘&lt;br&gt;
Editors: 😍&lt;br&gt;
CI/CD: 😎&lt;/p&gt;




&lt;h3&gt;
  
  
  🧘‍♂️ TL;DR
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stop redeploying manually — it’s 2025, not 2012.&lt;/li&gt;
&lt;li&gt;Use webhooks for automatic builds.&lt;/li&gt;
&lt;li&gt;Use ISR or on-demand revalidation for super-fast updates.&lt;/li&gt;
&lt;li&gt;Polling is fine… if you enjoy chaos.&lt;/li&gt;
&lt;li&gt;Automation = more free time + fewer Slack pings.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cicd</category>
      <category>productivity</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>Headless Adventures: From CMS to Frontend Without Losing Your Mind (5)</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Tue, 11 Nov 2025 09:56:06 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-5-3c63</link>
      <guid>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-5-3c63</guid>
      <description>&lt;h2&gt;
  
  
  🧾 Version Control for Content: Why Your CMS Needs Git-Like Superpowers
&lt;/h2&gt;

&lt;p&gt;You ever deploy your app, check the homepage, and suddenly your headline says “New Test Post #14”? 😭&lt;/p&gt;

&lt;p&gt;Yup. Someone “accidentally” hit publish on a draft.&lt;br&gt;
Welcome to &lt;strong&gt;content chaos&lt;/strong&gt; — where CMS editors move fast and &lt;em&gt;definitely&lt;/em&gt; break things.&lt;/p&gt;


&lt;h3&gt;
  
  
  🧠 The Core Problem
&lt;/h3&gt;

&lt;p&gt;We developers have Git.&lt;br&gt;
We commit, push, and revert with confidence.&lt;br&gt;
Meanwhile, CMS editors have... a “Save” button and hope.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Who changed the homepage title?”&lt;br&gt;
“Not me.”&lt;br&gt;
“Then why does it say ‘Coming Soon!!!’ in Comic Sans?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ladies and gentlemen, we need &lt;strong&gt;version control for content&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  💾 Why Versioning Matters
&lt;/h3&gt;

&lt;p&gt;Imagine your CMS like a Git repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each publish = a commit&lt;/li&gt;
&lt;li&gt;Each rollback = a revert&lt;/li&gt;
&lt;li&gt;Each editor = a contributor (with way too much enthusiasm)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With versioning, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restore deleted content&lt;/li&gt;
&lt;li&gt;Track who changed what&lt;/li&gt;
&lt;li&gt;Experiment safely (because undo exists)&lt;/li&gt;
&lt;li&gt;Sleep better at night 😴&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  🧩 Example: Strapi or Directus
&lt;/h3&gt;

&lt;p&gt;Modern headless CMSs like &lt;strong&gt;Strapi&lt;/strong&gt;, &lt;strong&gt;Directus&lt;/strong&gt;, and &lt;strong&gt;PayloadCMS&lt;/strong&gt; already give you revision systems — kind of like “mini Git histories” for your content.&lt;/p&gt;

&lt;p&gt;A sample record might look like this:&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dockploy + CMS: The Ultimate Pair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"edited_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lucas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-05T13:00:00Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can open previous versions, compare fields, and even restore old content.&lt;br&gt;
It’s like &lt;code&gt;git diff&lt;/code&gt;, but instead of code, you’re diffing between two blog post titles like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- "Dockploy + CMS: The Ultimate Pain"
+ "Dockploy + CMS: The Ultimate Pair"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Progress. 🧘‍♂️&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚙️ Step 1: Enable Draft &amp;amp; Publish Mode
&lt;/h3&gt;

&lt;p&gt;In Strapi or similar CMSs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;em&gt;Content Type Settings&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;Draft &amp;amp; Publish&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Boom — now your editors can save drafts without nuking production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because no one wants to see half-written posts live, like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Top 10… wait I’ll finish this later.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧱 Step 2: Store Version Metadata
&lt;/h3&gt;

&lt;p&gt;You can even extend your CMS model with version fields:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;previousVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;relation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api::post.post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;changeLog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, you can manually bump versions and keep a full “edit timeline.”&lt;/p&gt;




&lt;h3&gt;
  
  
  🔄 Step 3: Automate Backups (a.k.a. Don’t Trust Humans)
&lt;/h3&gt;

&lt;p&gt;Even with versioning, mistakes happen.&lt;br&gt;
So automate backups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Option 1:&lt;/strong&gt; Export your CMS data nightly to S3 or Google Cloud Storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option 2:&lt;/strong&gt; Use Dockploy’s scheduled jobs (if available) to run a backup script.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option 3:&lt;/strong&gt; Git commit your JSON exports daily — yep, literal content commits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because “oops, we lost yesterday’s blog” isn’t a fun Slack message. 😬&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 Step 4: Treat Content as Code
&lt;/h3&gt;

&lt;p&gt;If you’re feeling fancy, use the &lt;strong&gt;Content-as-Code&lt;/strong&gt; pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store your CMS content in Markdown or JSON files&lt;/li&gt;
&lt;li&gt;Keep them in a Git repo&lt;/li&gt;
&lt;li&gt;Deploy automatically when content changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Platforms like &lt;strong&gt;Netlify CMS&lt;/strong&gt; or &lt;strong&gt;Decap CMS&lt;/strong&gt; already do this!&lt;br&gt;
Each “edit” becomes a pull request — meaning you can review your editor’s “poetic” title changes before they go live. ✨&lt;/p&gt;




&lt;h3&gt;
  
  
  🧰 Step 5: Make It Fun
&lt;/h3&gt;

&lt;p&gt;If you want your team to actually use versioning, gamify it.&lt;/p&gt;

&lt;p&gt;Example idea:&lt;br&gt;
Every time someone restores a previous version, log:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“🕵️‍♂️ Detective Lucas just reverted a bad commit.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Positive reinforcement works, even in DevOps.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧘‍♂️ TL;DR
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Give your CMS Git-like powers — drafts, revisions, rollbacks.&lt;/li&gt;
&lt;li&gt;Always back up your content automatically.&lt;/li&gt;
&lt;li&gt;Treat content changes like code commits.&lt;/li&gt;
&lt;li&gt;Review before publishing (humans make typos, lots of them).&lt;/li&gt;
&lt;li&gt;Laugh at your mistakes — they’ll make great Dev.to posts later. 😄&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>git</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Headless Adventures: From CMS to Frontend Without Losing Your Mind (4)</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Fri, 07 Nov 2025 20:21:36 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-4-1e37</link>
      <guid>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-4-1e37</guid>
      <description>&lt;h2&gt;
  
  
  🚀 Dockploy + Headless CMS: Deploying Without Crying Over YAML Files
&lt;/h2&gt;

&lt;p&gt;If you’ve ever tried deploying a frontend connected to a headless CMS and ended up staring at a “502 Bad Gateway” page like it personally insulted you… this post is for you. 💀&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 The Mission
&lt;/h3&gt;

&lt;p&gt;You built something beautiful.&lt;br&gt;
Frontend? React or Next.js.&lt;br&gt;
Backend? Headless CMS.&lt;br&gt;
Everything works on localhost. You even high-fived yourself.&lt;/p&gt;

&lt;p&gt;Then it’s time to deploy — and suddenly your app behaves like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“CMS? Never heard of her.” 🤨&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  💣 The Old Way (a.k.a. The Deployment Pain Olympics)
&lt;/h3&gt;

&lt;p&gt;Before Dockploy, deployment meant juggling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dockerfiles that &lt;em&gt;kind of&lt;/em&gt; work&lt;/li&gt;
&lt;li&gt;CI/CD pipelines that fail silently&lt;/li&gt;
&lt;li&gt;YAML files that look like alien poetry&lt;/li&gt;
&lt;li&gt;Servers that say “connection refused” at 3AM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’d spend hours fixing environment variables until you start questioning your career choices.&lt;/p&gt;


&lt;h3&gt;
  
  
  🌤️ Enter Dockploy: The “Peaceful Deployment” Tool
&lt;/h3&gt;

&lt;p&gt;Dockploy is that rare friend who says,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hey, let’s deploy your app without emotional damage.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect your repo&lt;/li&gt;
&lt;li&gt;Choose your build command&lt;/li&gt;
&lt;li&gt;Link your environment variables&lt;/li&gt;
&lt;li&gt;Click &lt;em&gt;Deploy&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it. You’re live before your coffee gets cold. ☕&lt;/p&gt;


&lt;h3&gt;
  
  
  🧩 Step 1: Set Your Environment Variables
&lt;/h3&gt;

&lt;p&gt;Your CMS URL, API key, and frontend endpoint are best friends — until one of them goes missing.&lt;/p&gt;

&lt;p&gt;In Dockploy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Environment Variables&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Add keys like:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  NEXT_PUBLIC_CMS_URL=https://cms.example.com
  CMS_TOKEN=super-secret-token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Hit save&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Never hardcode secrets, unless you enjoy being hacked by future-you. 🔒&lt;/p&gt;


&lt;h3&gt;
  
  
  🧱 Step 2: Configure Your Build
&lt;/h3&gt;

&lt;p&gt;Dockploy detects your stack automatically (Next.js, Astro, Remix — whatever you fancy).&lt;br&gt;
But just to be safe:&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;# Build&lt;/span&gt;
pnpm build

&lt;span class="c"&gt;# Start (if needed)&lt;/span&gt;
pnpm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if your CMS API runs on another server, make sure it’s reachable — nothing says “oops” like a 404 from your backend.&lt;/p&gt;




&lt;h3&gt;
  
  
  🛰️ Step 3: Connect Frontend + CMS Smoothly
&lt;/h3&gt;

&lt;p&gt;If your CMS (like Strapi or Directus) runs on another Dockploy app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use internal URLs or Docker network aliases&lt;/li&gt;
&lt;li&gt;Example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  NEXT_PUBLIC_CMS_URL=http://cms:1337
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of &lt;code&gt;localhost&lt;/code&gt; or some random IP that only your cat understands. 🐱&lt;/p&gt;

&lt;p&gt;Now your frontend and backend are besties again.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧙 Step 4: Add Automatic Redeploys (Because You Deserve It)
&lt;/h3&gt;

&lt;p&gt;Nothing feels better than pushing to &lt;code&gt;main&lt;/code&gt; and seeing Dockploy say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Got it, boss. Redeploying automatically.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can link GitHub → Dockploy and set up automatic deploys for every push.&lt;/p&gt;

&lt;p&gt;It’s basically like CI/CD, but without 3,000 YAML lines. 🪄&lt;/p&gt;




&lt;h3&gt;
  
  
  🔥 Step 5: Debug Without Tears
&lt;/h3&gt;

&lt;p&gt;If something breaks (it will), Dockploy logs are your best friend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Logs&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You’ll instantly see which env var you forgot, or which import you misspelled&lt;/li&gt;
&lt;li&gt;Fix → push → redeploy → brag&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🎉 Step 6: Celebrate and Pretend It Was Easy
&lt;/h3&gt;

&lt;p&gt;Now that your CMS and frontend are deployed and talking nicely,&lt;br&gt;
you can act cool in your dev chat:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Yeah, just deployed to Dockploy. Zero config. Smooth.” 😎&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(&lt;em&gt;You totally forgot to add the &lt;code&gt;.env&lt;/code&gt; file on your first try, but no one needs to know.&lt;/em&gt;)&lt;/p&gt;




&lt;h3&gt;
  
  
  🧘‍♂️ TL;DR
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Set your env vars — don’t hardcode secrets.&lt;/li&gt;
&lt;li&gt;Let Dockploy auto-detect your build setup.&lt;/li&gt;
&lt;li&gt;Use internal URLs if your CMS and frontend live together.&lt;/li&gt;
&lt;li&gt;Enable automatic redeploys — future-you will love it.&lt;/li&gt;
&lt;li&gt;Celebrate like you didn’t just Google “docker network alias” 6 times.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>tooling</category>
      <category>devops</category>
      <category>docker</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Headless Adventures: From CMS to Frontend Without Losing Your Mind (3)</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Thu, 06 Nov 2025 21:26:13 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-3-1od4</link>
      <guid>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-3-1od4</guid>
      <description>&lt;h2&gt;
  
  
  🎨 Frontend Rendering Magic: Building Dynamic Pages From CMS Data (Without Crying)
&lt;/h2&gt;

&lt;p&gt;So, you’ve fetched your shiny CMS data, mapped it beautifully, and you’re feeling powerful.&lt;br&gt;
Then you try to render it on the frontend, and suddenly...&lt;br&gt;
💥 &lt;em&gt;“TypeError: Cannot read properties of undefined (reading 'map')”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Welcome to the glamorous life of frontend developers.&lt;/p&gt;


&lt;h3&gt;
  
  
  🧠 Scene 1: The Dream
&lt;/h3&gt;

&lt;p&gt;You imagine a perfect world where your CMS sends this:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"post-1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"post-2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and your frontend smoothly renders:&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;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PostCard&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&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;It works. You deploy. You smile. Life is good. ☀️&lt;/p&gt;




&lt;h3&gt;
  
  
  💀 Scene 2: The Reality
&lt;/h3&gt;

&lt;p&gt;Two days later, your content editor adds a new “Featured” section in the CMS.&lt;br&gt;
Now the response looks like:&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;"posts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"post-1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post 2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"post-2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"featured"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You reload your page.&lt;br&gt;
💣 &lt;em&gt;“Cannot read properties of null (reading 'map')”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your perfect app now screams louder than your coffee machine on Monday. ☕😩&lt;/p&gt;


&lt;h3&gt;
  
  
  🛠️ Step 1: Always Guard Your Maps
&lt;/h3&gt;

&lt;p&gt;It’s 2025. If you’re still doing &lt;code&gt;data.map()&lt;/code&gt;, you’re basically coding without a seatbelt.&lt;br&gt;
Do this instead:&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;{&lt;/span&gt;&lt;span class="nx"&gt;data&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PostCard&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="si"&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;item&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="p"&gt;:&lt;/span&gt; &lt;span class="p"&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;No posts found 😭&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;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or go fancier:&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;{&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderPost&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EmptyState&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Nothing to show, just vibes ✨"&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;h3&gt;
  
  
  🎭 Step 2: The “Dynamic Page” Drama
&lt;/h3&gt;

&lt;p&gt;You fetch your post list and want to render individual post pages dynamically.&lt;br&gt;
If you’re using &lt;strong&gt;Next.js&lt;/strong&gt;, you’ll go through the famous phase:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Wait, getStaticPaths… getStaticProps… getServerSideProps… which one again!?” 😵‍💫&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simplify it:&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="c1"&gt;// pages/[slug].js&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;getStaticPaths&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;fetchPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;paths&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&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="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;fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blocking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="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;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&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;post&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;fetchPostBySlug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&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;Boom.&lt;br&gt;
You’ve just mastered &lt;strong&gt;SSG + ISR&lt;/strong&gt; with one caffeine shot. ☕⚡&lt;/p&gt;


&lt;h3&gt;
  
  
  🧩 Step 3: Componentize Like a Legend
&lt;/h3&gt;

&lt;p&gt;If your CMS has sections like “Hero”, “Gallery”, “Testimonials” — don’t hardcode them.&lt;br&gt;
Instead, use a &lt;em&gt;component resolver pattern&lt;/em&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="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;HeroSection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gallery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GallerySection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;testimonials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestimonialsSection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;blocks&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;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;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="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;Component&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;p&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;🤔 Unknown block: &lt;span class="si"&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;type&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;
        &lt;span class="k"&gt;return&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&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;block&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="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;Now when your CMS team adds a new section called &lt;code&gt;“weird-experimental-banner”&lt;/code&gt;,&lt;br&gt;
you just add a component and roll with it. 😎&lt;/p&gt;


&lt;h3&gt;
  
  
  🐞 Step 4: Handle CMS “Creativity” Gracefully
&lt;/h3&gt;

&lt;p&gt;There will be times when your CMS data…&lt;br&gt;
&lt;em&gt;doesn’t make sense.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Like this:&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;"hero"&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;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"button"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Read more"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, guard your rendering logic like a bouncer at a nightclub:&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;{&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Hero&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&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="p"&gt;:&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;FallbackHero&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"This hero is shy today 😅"&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;Your users won’t see chaos — only charm. 💅&lt;/p&gt;




&lt;h3&gt;
  
  
  🚀 Step 5: Deploy and Brag
&lt;/h3&gt;

&lt;p&gt;Once it all works, deploy it on &lt;strong&gt;Dockploy&lt;/strong&gt; (or your platform of choice).&lt;br&gt;
Bonus points if you act like it was easy in front of your team:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Yeah, dynamic routing with CMS content? Took like 10 minutes.” 😏&lt;br&gt;
(&lt;em&gt;Meanwhile, your commit history looks like a battlefield.&lt;/em&gt;)&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧘‍♂️ TL;DR
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Guard your data before you render it.&lt;/li&gt;
&lt;li&gt;Use component mapping for dynamic sections.&lt;/li&gt;
&lt;li&gt;Learn your rendering methods (SSR, SSG, ISR — they’re not just buzzwords).&lt;/li&gt;
&lt;li&gt;Handle weird CMS data with humor, not panic.&lt;/li&gt;
&lt;li&gt;Deploy with pride, even if it took three breakdowns and a nap.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Headless Adventures: From CMS to Frontend Without Losing Your Mind (2)</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Tue, 04 Nov 2025 23:21:22 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-2-4k0o</link>
      <guid>https://dev.to/lucasbrdt268/headless-adventures-from-cms-to-frontend-without-losing-your-mind-2-4k0o</guid>
      <description>&lt;h2&gt;
  
  
  Mapping Headless CMS Data to Your Frontend Like a Pro
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;(a.k.a. How to Stop Yelling at Your JSON)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You finally connected your frontend to your headless CMS. Congratulations! 🎉&lt;br&gt;
Now comes the part that separates the &lt;em&gt;rookies&lt;/em&gt; from the &lt;em&gt;battle-hardened devs&lt;/em&gt;: &lt;strong&gt;mapping CMS data&lt;/strong&gt; into something your frontend actually understands.&lt;/p&gt;

&lt;p&gt;Because let’s face it — the data structure your CMS gives you and the one you &lt;em&gt;want&lt;/em&gt; are rarely the same species. 🦧&lt;/p&gt;


&lt;h3&gt;
  
  
  🤯 The Typical Scenario
&lt;/h3&gt;

&lt;p&gt;Your CMS sends this beauty:&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;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&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;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My First Blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"author_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lucas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;p&amp;gt;Hello world!&amp;lt;/p&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But your React component just wants:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;My First Blog&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello world!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first time I saw this, I said, “Surely there’s an easier way.”&lt;br&gt;
Then I mapped it manually for two hours and cried softly into my keyboard. 🧑‍💻💧&lt;/p&gt;


&lt;h3&gt;
  
  
  🛠️ Step 1: Normalize the Data
&lt;/h3&gt;

&lt;p&gt;Here’s the golden rule: &lt;strong&gt;Don’t pass CMS data directly into your components.&lt;/strong&gt;&lt;br&gt;
You want clean, predictable data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;normalizePost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cmsPost&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cmsPost&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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="c1"&gt;// optional cleanup&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;Then when you fetch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cms.example.com/api/posts&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;json&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;res&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="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="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;normalizePost&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boom. 💥 Now your frontend gets exactly what it wants.&lt;/p&gt;




&lt;h3&gt;
  
  
  🎯 Step 2: Create a Mapper Layer
&lt;/h3&gt;

&lt;p&gt;If you work on large projects, &lt;strong&gt;create a separate folder&lt;/strong&gt; for mapping/transforming data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
 ┣ api/
 ┃ ┣ cms.js
 ┃ ┗ mapper.js
 ┗ components/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;mapper.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapAuthor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;avatar&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;You get &lt;strong&gt;clean, maintainable data transformations&lt;/strong&gt;, and your components stay lightweight and happy.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚡ Step 3: Handle Missing or Weird Fields
&lt;/h3&gt;

&lt;p&gt;Real talk: CMS editors &lt;em&gt;will&lt;/em&gt; forget to fill something in.&lt;br&gt;
So instead of your app exploding, give it a hug:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Untitled Post&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author_name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Anonymous&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No content yet...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional chaining helps too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Untitled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧠 Step 4: Version Your Mappers
&lt;/h3&gt;

&lt;p&gt;CMS data structures &lt;strong&gt;change&lt;/strong&gt; over time.&lt;br&gt;
You add a field. You rename something. You forget what you did. 😅&lt;/p&gt;

&lt;p&gt;To keep your sanity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add comments or JSDoc for each mapper&lt;/li&gt;
&lt;li&gt;Keep old mappers until migrations are done&lt;/li&gt;
&lt;li&gt;Write simple unit tests for your mappings (trust me, future-you will be grateful)&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  🧩 Step 5: Feed the Frontend
&lt;/h3&gt;

&lt;p&gt;Now, when you render posts:&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;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PostCard&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s clean. Predictable. Reliable.&lt;br&gt;
Like that one friend who always brings snacks to debugging sessions. 🍪&lt;/p&gt;


&lt;h3&gt;
  
  
  🚀 Bonus: Add TypeScript (If You Like Type Safety and Pain)
&lt;/h3&gt;

&lt;p&gt;If you’re using TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CMSPost&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;author_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&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="nl"&gt;author&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="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mapPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CMSPost&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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;Your IDE now catches 80% of your future headaches automatically. 🧘‍♂️&lt;/p&gt;




&lt;h3&gt;
  
  
  ✍️ TL;DR
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Normalize your data.&lt;/strong&gt; Never use raw CMS responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a mapper layer.&lt;/strong&gt; Keep logic out of components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle missing fields.&lt;/strong&gt; Gracefully, not dramatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version your mappers.&lt;/strong&gt; Change is inevitable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider TypeScript.&lt;/strong&gt; Or don’t. Your choice.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>api</category>
      <category>frontend</category>
      <category>tutorial</category>
      <category>react</category>
    </item>
    <item>
      <title>Headless Adventures: From CMS to Frontend Without Losing Your Mind (1)</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Sat, 01 Nov 2025 13:43:00 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/integrating-headless-cms-with-your-frontend-without-losing-your-mind-4f9g</link>
      <guid>https://dev.to/lucasbrdt268/integrating-headless-cms-with-your-frontend-without-losing-your-mind-4f9g</guid>
      <description>&lt;h2&gt;
  
  
  Integrating Headless CMS With Your Frontend Without Losing Your Mind
&lt;/h2&gt;




&lt;p&gt;Let’s be real. &lt;strong&gt;Headless CMS&lt;/strong&gt; sounds amazing in theory:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Just content in the back, frontend in the front. Easy!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In practice… it can feel like trying to teach a cat to code. 🐱💻&lt;/p&gt;

&lt;p&gt;Here’s how I survived integrating a &lt;strong&gt;Headless CMS&lt;/strong&gt;, built a &lt;strong&gt;frontend&lt;/strong&gt; that didn’t crash on launch, and deployed it with &lt;strong&gt;Dockploy&lt;/strong&gt; — without losing all my hair.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Step 1: Understand Your Headless CMS
&lt;/h2&gt;

&lt;p&gt;A headless CMS is basically:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I’ll give you the data. You figure out how to display it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ve worked with Strapi, Contentful, Ghost, and a few custom CMSs. They all share a common trait: they &lt;strong&gt;send perfect data… as long as you can fetch it correctly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Always check your &lt;strong&gt;GraphQL/REST endpoint&lt;/strong&gt; first.&lt;br&gt;
Think of it like checking your GPS before a road trip — saves you from driving into a swamp. 🛶&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚡ Step 2: Connect the Frontend
&lt;/h2&gt;

&lt;p&gt;I built my frontend in React (but Vue, Svelte, or Next.js works too — I don’t discriminate).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cms.example.com/api/posts&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;data&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;res&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;return&lt;/span&gt; &lt;span class="nx"&gt;data&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip 1:&lt;/strong&gt; Use &lt;code&gt;async/await&lt;/code&gt; — your users will thank you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tip 2:&lt;/strong&gt; Handle errors gracefully. Users don’t want to see &lt;code&gt;[object Object]&lt;/code&gt; on the homepage.
&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;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;fetchPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;renderPosts&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;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CMS fetch 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;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;showErrorMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Oops! Something went wrong.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🪄 Step 3: Integration Gotchas
&lt;/h2&gt;

&lt;p&gt;Here’s where most devs cry silently into their coffee mugs: ☕&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CORS issues&lt;/strong&gt; — your frontend and CMS are on different domains.&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Add correct CORS headers in the CMS or use a proxy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Field naming differences&lt;/strong&gt; — CMS returns &lt;code&gt;author_name&lt;/code&gt;, frontend expects &lt;code&gt;authorName&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Map fields or normalize them in a helper function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nested data nightmares&lt;/strong&gt; — &lt;code&gt;categories[0].posts[0].title&lt;/code&gt; sometimes turns out &lt;code&gt;null&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Optional chaining saves lives: &lt;code&gt;categories?.[0]?.posts?.[0]?.title || "Untitled"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🚀 Step 4: Deploy With Dockploy
&lt;/h2&gt;

&lt;p&gt;Once everything works locally, deployment time arrives. I used &lt;strong&gt;Dockploy&lt;/strong&gt; because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It handles &lt;strong&gt;containerized apps&lt;/strong&gt; beautifully&lt;/li&gt;
&lt;li&gt;Supports multiple environments&lt;/li&gt;
&lt;li&gt;Keeps your CI/CD sane&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deploying a React app integrated with a headless CMS is as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dockploy deploy &lt;span class="nt"&gt;--project&lt;/span&gt; my-frontend &lt;span class="nt"&gt;--env&lt;/span&gt; production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boom 💥 — live site, zero tears… almost.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test API endpoints first.&lt;/strong&gt; Don’t trust docs blindly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalize your data.&lt;/strong&gt; Your frontend is picky.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle errors gracefully.&lt;/strong&gt; Users hate ugly crashes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dockploy saves your life.&lt;/strong&gt; Seriously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And most importantly: &lt;strong&gt;laugh when things break.&lt;/strong&gt;&lt;br&gt;
If you can’t laugh at a 500 error at 11 PM, are you even a dev? 😎&lt;/p&gt;




&lt;h2&gt;
  
  
  ✍️ TL;DR
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Headless CMS = content only. Frontend = your playground.&lt;/li&gt;
&lt;li&gt;Fetch data safely, handle errors, normalize fields.&lt;/li&gt;
&lt;li&gt;Use Dockploy for smooth deployment.&lt;/li&gt;
&lt;li&gt;Laugh at your mistakes, then fix them.&lt;/li&gt;
&lt;/ol&gt;




</description>
    </item>
    <item>
      <title>The Final Showdown: Choosing the Right Rendering Strategy Without Losing Your Mind</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Mon, 20 Oct 2025 22:51:30 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/the-final-showdown-choosing-the-right-rendering-strategy-without-losing-your-mind-15i9</link>
      <guid>https://dev.to/lucasbrdt268/the-final-showdown-choosing-the-right-rendering-strategy-without-losing-your-mind-15i9</guid>
      <description>&lt;p&gt;You’ve made it, hero. 🧙‍♂️&lt;br&gt;
You fought through the Great War of SSR vs CSR, danced with SSG, flirted with ISR, and stared into the abyss of Edge Rendering.&lt;/p&gt;

&lt;p&gt;Now there’s only one question left:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Which rendering strategy should I actually use… without losing my sanity?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Grab your caffeine. We’re going in.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚔️ The Cast (Quick Recap)
&lt;/h2&gt;

&lt;p&gt;Let’s reintroduce our lovely chaos crew:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rendering Type&lt;/th&gt;
&lt;th&gt;Motto&lt;/th&gt;
&lt;th&gt;Personality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CSR (Client-Side Rendering)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;“I’ll do it myself.”&lt;/td&gt;
&lt;td&gt;Independent, but lazy at first.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSR (Server-Side Rendering)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;“I’ll prepare it fresh, just for you.”&lt;/td&gt;
&lt;td&gt;Polite waiter, slow under pressure.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSG (Static Site Generation)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;“I made this yesterday, hope you like it.”&lt;/td&gt;
&lt;td&gt;Fast, predictable, allergic to updates.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ISR (Incremental Static Regeneration)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;“I update... sometimes.”&lt;/td&gt;
&lt;td&gt;Lazy genius who sets reminders.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Edge Rendering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;“I’m everywhere.”&lt;/td&gt;
&lt;td&gt;The world traveler, powered by caffeine and V8.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧩 The Real-World Problem
&lt;/h2&gt;

&lt;p&gt;You’ve got a project. You’re trying to pick a rendering strategy.&lt;br&gt;
But every doc, blog, and YouTuber says &lt;em&gt;“It depends.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So here’s what it &lt;strong&gt;actually depends&lt;/strong&gt; on — simplified by someone who’s deployed too many times at 2 AM. ☕💀&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 Choose Your Fighter: The Decision Map
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;               ┌──→ Do you need SEO?
               │         │
               │         ├─ Yes → SSR or SSG
Need SEO? ─────┤         │
               │         └─ No  → CSR (you’re free!)
               │
               │
               └──→ Does data change often?
                         │
                         ├─ Rarely → SSG
                         │
                         ├─ Sometimes → ISR
                         │
                         └─ Always → SSR or Edge Rendering
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if you’re more of a “vibes-based” engineer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🥶 If it never changes → SSG&lt;br&gt;
😎 If it changes sometimes → ISR&lt;br&gt;
🔥 If it changes often → SSR&lt;br&gt;
⚡ If your users live everywhere → Edge Rendering&lt;br&gt;
💀 If you hate yourself → Mix them all and pray&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💡 Real Examples
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Rendering Strategy&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blog&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SSG&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast, static, minimal updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce product page&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ISR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stock &amp;amp; price updates every few mins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;News site&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SSR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real-time updates + SEO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard / SaaS&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CSR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Logged-in data only, no SEO needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global app (like a weather site)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Edge Rendering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Needs low latency for everyone&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧱 Hybrid Is the New Normal
&lt;/h2&gt;

&lt;p&gt;Modern frameworks like &lt;strong&gt;Next.js&lt;/strong&gt; and &lt;strong&gt;Nuxt&lt;/strong&gt; are like a buffet — mix and match whatever rendering style fits each page.&lt;/p&gt;

&lt;p&gt;You can literally have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/about&lt;/code&gt; → &lt;strong&gt;SSG&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/products&lt;/code&gt; → &lt;strong&gt;ISR&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/checkout&lt;/code&gt; → &lt;strong&gt;SSR&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/dashboard&lt;/code&gt; → &lt;strong&gt;CSR&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/realtime-weather&lt;/code&gt; → &lt;strong&gt;Edge&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, it’s a mess… but it’s a &lt;em&gt;beautiful mess&lt;/em&gt;. ❤️&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Real Talk from Experience
&lt;/h2&gt;

&lt;p&gt;Here’s what years of trial, error, and coffee have taught me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t over-engineer&lt;/strong&gt;. Most sites don’t need Edge Functions unless you’re building Twitter 2.0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Think about updates&lt;/strong&gt; — how often does your content &lt;em&gt;actually&lt;/em&gt; change?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure&lt;/strong&gt; before switching strategies. If users aren’t complaining, you might already be fast enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy often, panic less.&lt;/strong&gt; Everything looks perfect locally — until it’s live. 😅&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏁 TL;DR (for your team meeting)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Goal&lt;/th&gt;
&lt;th&gt;Best Pick&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Super fast &amp;amp; rarely changes&lt;/td&gt;
&lt;td&gt;🧊 SSG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEO + fresh data&lt;/td&gt;
&lt;td&gt;🔥 SSR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mostly static but updates sometimes&lt;/td&gt;
&lt;td&gt;⏰ ISR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logged-in dashboard&lt;/td&gt;
&lt;td&gt;🧠 CSR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global traffic, minimal latency&lt;/td&gt;
&lt;td&gt;🌍 Edge Rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🎤 Final Words
&lt;/h2&gt;

&lt;p&gt;Choosing a rendering strategy is like dating —&lt;br&gt;
everyone looks perfect until you actually deploy them.&lt;/p&gt;

&lt;p&gt;Start simple, learn how each behaves under pressure, and remember:&lt;br&gt;
&lt;strong&gt;no rendering method can fix bad UX, ugly UI, or that one teammate who pushes to &lt;code&gt;main&lt;/code&gt; on Fridays.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✍️ About the Author
&lt;/h2&gt;

&lt;p&gt;Hey, I’m &lt;strong&gt;Lucas&lt;/strong&gt; — the guy who’s broken production servers so you don’t have to.&lt;br&gt;
I write about real-world web dev, with a mix of caffeine, sarcasm, and lessons learned the hard way.&lt;br&gt;
Follow me if you like code that works &lt;em&gt;most&lt;/em&gt; of the time. 😎&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>architecture</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Edge Rendering — Because Apparently the Server Wasn’t Close Enough</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Fri, 17 Oct 2025 05:37:14 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/edge-rendering-because-apparently-the-server-wasnt-close-enough-54jj</link>
      <guid>https://dev.to/lucasbrdt268/edge-rendering-because-apparently-the-server-wasnt-close-enough-54jj</guid>
      <description>&lt;p&gt;Remember the days when “faster websites” just meant &lt;strong&gt;compressing images&lt;/strong&gt; and &lt;strong&gt;yelling at the intern who forgot to minify CSS&lt;/strong&gt;?&lt;br&gt;
Yeah… simpler times.&lt;/p&gt;

&lt;p&gt;Now we have &lt;strong&gt;Edge Rendering&lt;/strong&gt; — because, apparently, the &lt;em&gt;server&lt;/em&gt; sitting quietly in Virginia just wasn’t close enough to your user in Tokyo.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 The Big Idea
&lt;/h2&gt;

&lt;p&gt;Traditional &lt;strong&gt;SSR (Server-Side Rendering)&lt;/strong&gt; happens on your main server — usually somewhere far, far away.&lt;br&gt;
That means every request has to go on a little world tour before coming back. 🌏✈️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edge Rendering&lt;/strong&gt; says,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Nah, let’s just move the rendering closer to the user.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So instead of one server in the U.S., you get &lt;strong&gt;tiny server clones&lt;/strong&gt; (Edge Functions) scattered across the planet — Tokyo, London, Paris, maybe even Antarctica someday.&lt;/p&gt;

&lt;p&gt;The result?&lt;br&gt;
Faster response, lower latency, and fewer users rage-quitting your site because it loaded slower than their grandma’s Wi-Fi.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚙️ How It Works
&lt;/h2&gt;

&lt;p&gt;Let’s say you’re using &lt;strong&gt;Next.js on Vercel&lt;/strong&gt; (the cool kids’ combo).&lt;/p&gt;

&lt;p&gt;When someone visits your page:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The request goes to the &lt;strong&gt;nearest edge location&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;lightweight runtime&lt;/strong&gt; (like V8 isolates or WebAssembly) executes your rendering logic.&lt;/li&gt;
&lt;li&gt;HTML gets streamed back to the user — before your server even finishes yawning awake.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Basically, you’re doing SSR… but on steroids. 💪&lt;/p&gt;


&lt;h2&gt;
  
  
  🔥 Example
&lt;/h2&gt;

&lt;p&gt;In Next.js, enabling Edge Rendering is as simple as telling your page to live on the edge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;edge&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&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;data&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;res&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;Edge&lt;/span&gt; &lt;span class="err"&gt;👋&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;pre&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/pre&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it.&lt;br&gt;
No more giant server configs, no sweaty &lt;code&gt;nginx&lt;/code&gt; logs.&lt;br&gt;
Just modern, global rendering magic.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚔️ Edge vs SSR vs CSR (Quick Comparison)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Where It Renders&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Can Fetch Secure Data?&lt;/th&gt;
&lt;th&gt;When to Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CSR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Browser&lt;/td&gt;
&lt;td&gt;🚶‍♂️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;SPAs, dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Central server&lt;/td&gt;
&lt;td&gt;🏃‍♂️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;SEO + dynamic data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Edge Rendering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nearest node&lt;/td&gt;
&lt;td&gt;🏎️💨&lt;/td&gt;
&lt;td&gt;✅ (limited)&lt;/td&gt;
&lt;td&gt;Global apps needing speed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧩 Limitations
&lt;/h2&gt;

&lt;p&gt;Let’s be real — edge functions are fast, but not perfect.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No full Node.js APIs (you’re in a sandbox).&lt;/li&gt;
&lt;li&gt;Cold starts can still happen (though short).&lt;/li&gt;
&lt;li&gt;Debugging globally distributed bugs? …Good luck, my friend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But for latency-sensitive apps (e.g. e-commerce, geolocation, dynamic content), it’s a game changer.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Real Talk
&lt;/h2&gt;

&lt;p&gt;Edge Rendering is like moving your restaurant from one city to hundreds of small food stalls around the world.&lt;br&gt;
Sure, setup’s trickier — but your customers get their meal faster, hotter, and happier. 🍔✨&lt;/p&gt;

&lt;p&gt;If you’re using &lt;strong&gt;Vercel&lt;/strong&gt;, &lt;strong&gt;Cloudflare Workers&lt;/strong&gt;, or &lt;strong&gt;Netlify Edge Functions&lt;/strong&gt;, congratulations — you’re already living in the future.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Edge Rendering = SSR that’s been hitting the gym.&lt;/li&gt;
&lt;li&gt;It renders &lt;em&gt;closer to your users&lt;/em&gt;, reducing latency.&lt;/li&gt;
&lt;li&gt;Great for global apps, but with some runtime restrictions.&lt;/li&gt;
&lt;li&gt;It’s the next step toward the dream of “instant everything.”&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;“Move your rendering closer to the users,” they said.&lt;br&gt;
“It’ll be fun,” they said.&lt;/p&gt;

&lt;p&gt;Every Dev Who Debugged Edge Functions at 3AM 😅&lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>serverless</category>
      <category>webdev</category>
      <category>performance</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Hydration Hell — Why React Yells at You After SSR</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Wed, 15 Oct 2025 19:43:55 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/frontend-wars-hydration-hell-why-react-yells-at-you-after-ssr-1co2</link>
      <guid>https://dev.to/lucasbrdt268/frontend-wars-hydration-hell-why-react-yells-at-you-after-ssr-1co2</guid>
      <description>&lt;p&gt;Welcome back, brave devs.&lt;br&gt;
In our last episode, we talked about &lt;strong&gt;ISR vs SSG&lt;/strong&gt;, where pages regenerate like responsible adults.&lt;/p&gt;

&lt;p&gt;But today…&lt;br&gt;
We enter a darker realm.&lt;br&gt;
A place filled with &lt;strong&gt;cryptic console warnings&lt;/strong&gt;, weird mismatched DOMs, and the haunting whisper of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Warning: Text content did not match. Server: ‘Hello’ Client: ‘Hi’”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yep. Welcome to &lt;strong&gt;Hydration Hell.&lt;/strong&gt; 😈&lt;/p&gt;


&lt;h2&gt;
  
  
  ☠️ What Is Hydration, Anyway?
&lt;/h2&gt;

&lt;p&gt;So you’ve just rendered your shiny React app &lt;strong&gt;on the server (SSR)&lt;/strong&gt;.&lt;br&gt;
The server sends &lt;em&gt;fully built HTML&lt;/em&gt; to the browser — awesome, users see content instantly!&lt;/p&gt;

&lt;p&gt;But now, React needs to attach its magical event listeners to that HTML.&lt;br&gt;
That process is called &lt;strong&gt;hydration&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Basically:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“React looks at your HTML and says, ‘Alright, I made this earlier. Let’s reconnect and make it alive again.’”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s like reviving a zombie app 🧟 — the HTML is there, but React breathes life into it.&lt;/p&gt;


&lt;h2&gt;
  
  
  💣 When Hydration Goes Wrong
&lt;/h2&gt;

&lt;p&gt;Everything looks fine… until React starts yelling at you in the console like a disappointed parent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Warning: Text content did not match.
Server: "Hello SSR"
Client: "Hello Client"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;br&gt;
Because the HTML your server sent &lt;strong&gt;doesn’t match&lt;/strong&gt; what React tries to render on the client.&lt;/p&gt;

&lt;p&gt;That mismatch causes React to freak out, tear down parts of the DOM, and rebuild them — ruining your performance and sometimes your will to live.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔥 Common Causes of Hydration Errors
&lt;/h2&gt;

&lt;p&gt;Let’s go through the main culprits — I call them &lt;strong&gt;The Four Horsemen of Hydration Hell&lt;/strong&gt;:&lt;/p&gt;
&lt;h3&gt;
  
  
  🐴 1. Random Values in Render
&lt;/h3&gt;

&lt;p&gt;You used &lt;code&gt;Math.random()&lt;/code&gt;, &lt;code&gt;Date.now()&lt;/code&gt;, or something equally chaotic inside your React render.&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="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;Hero&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;ID: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&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;h1&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;Server: renders &lt;code&gt;ID: 0.1234&lt;/code&gt;&lt;br&gt;
Client: renders &lt;code&gt;ID: 0.9876&lt;/code&gt;&lt;br&gt;
React: “Bro, what even is this?” 😡&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
Only use random or time-based stuff &lt;strong&gt;inside useEffect&lt;/strong&gt;, not during render.&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="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;Hero&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;ID: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&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;h1&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;h3&gt;
  
  
  🐴 2. Conditional Rendering Differences
&lt;/h3&gt;

&lt;p&gt;Server says: “User is logged out.”&lt;br&gt;
Client says: “Actually, I found a token in localStorage.”&lt;/p&gt;

&lt;p&gt;Boom. Mismatch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
Don’t render user-dependent stuff during SSR unless you &lt;em&gt;actually know&lt;/em&gt; the user state.&lt;br&gt;
Render a placeholder and hydrate the real data later.&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;{&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&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;)&lt;/span&gt; &lt;span class="p"&gt;:&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;UserDashboard&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;h3&gt;
  
  
  🐴 3. Data Fetching Madness
&lt;/h3&gt;

&lt;p&gt;You fetched data &lt;strong&gt;client-side only&lt;/strong&gt;, so SSR HTML was empty, but client added content later.&lt;br&gt;
React gets confused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
Use &lt;code&gt;getServerSideProps&lt;/code&gt;, &lt;code&gt;getStaticProps&lt;/code&gt;, or a similar prefetch method.&lt;br&gt;
Or, if you’re using CSR for certain parts, wrap them in dynamic imports (Next.js style):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NoSSRComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&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;./Chart&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;ssr&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🐴 4. Third-Party Scripts That Love Chaos
&lt;/h3&gt;

&lt;p&gt;Some scripts (like ads, widgets, analytics) mutate the DOM between server render and hydration.&lt;/p&gt;

&lt;p&gt;React: “I didn’t put that there.”&lt;br&gt;
Browser: “It was the marketing team.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
Run those scripts &lt;strong&gt;after hydration&lt;/strong&gt; — usually inside a &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧙‍♂️ Debugging Hydration Errors Like a Pro
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with a clean console&lt;/strong&gt; — hydrate, refresh, see what breaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare SSR HTML vs Client HTML&lt;/strong&gt; (use “View Page Source” vs DevTools “Elements”).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search for differences&lt;/strong&gt;: random numbers, dates, user state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporarily disable SSR&lt;/strong&gt; for components one by one to isolate the troublemaker.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Debugging hydration is like solving a murder mystery — except the suspect is always your own code. 🕵️‍♂️&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚡ Pro Tip: Use “Suspense” Wisely
&lt;/h2&gt;

&lt;p&gt;React 18+ hydration supports streaming, partial hydration, and suspense.&lt;br&gt;
If your page is slow to hydrate, &lt;strong&gt;split components&lt;/strong&gt; and hydrate parts gradually:&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;Suspense&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;Loading chart...&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;Chart&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;Suspense&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 keeps the UI interactive while React hydrates other sections.&lt;br&gt;
Basically, you hydrate &lt;em&gt;without burning down the CPU.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🪄 TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hydration&lt;/strong&gt; = React reattaching event listeners to SSR HTML.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Common problems&lt;/strong&gt;: random values, client-only data, mismatched conditions, rogue scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solutions&lt;/strong&gt;: keep SSR deterministic, delay browser-only logic, use &lt;code&gt;useEffect&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If React yells at you about mismatched content, it’s not being mean — it’s just confused about your life choices.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  😂 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Hydration errors are like hangovers:&lt;br&gt;
You can avoid them if you just plan responsibly the night before.&lt;/p&gt;

&lt;p&gt;SSR gives your app a fast first impression,&lt;br&gt;
Hydration keeps it alive.&lt;br&gt;
Mess them up, and your user gets both a flash of content &lt;em&gt;and&lt;/em&gt; a console full of regrets.&lt;/p&gt;




&lt;p&gt;Next time on &lt;strong&gt;Frontend Wars&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚡ &lt;em&gt;Edge Rendering: Because Apparently the Server Wasn’t Close Enough&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We’ll talk about how your code now runs in data centers closer to your users — and why that’s both cool and terrifying.&lt;/p&gt;

&lt;p&gt;Stay hydrated, developers. 💧&lt;/p&gt;




</description>
    </item>
    <item>
      <title>ISR vs SSG — When Your App Wants to Sleep but SEO Won’t Let It</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Wed, 15 Oct 2025 01:20:59 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/isr-vs-ssg-when-your-app-wants-to-sleep-but-seo-wont-let-it-2ke4</link>
      <guid>https://dev.to/lucasbrdt268/isr-vs-ssg-when-your-app-wants-to-sleep-but-seo-wont-let-it-2ke4</guid>
      <description>&lt;h1&gt;
  
  
  🧠 Frontend Wars: ISR vs SSG — When Your App Wants to Sleep but SEO Won’t Let It
&lt;/h1&gt;

&lt;p&gt;Welcome back, brave developer!&lt;br&gt;
Last time, we battled &lt;strong&gt;SSR vs CSR&lt;/strong&gt;, a war between servers and browsers that left many laptops overheating and many devs emotionally scarred.&lt;/p&gt;

&lt;p&gt;Today’s fight?&lt;br&gt;
It’s between two &lt;em&gt;cousins&lt;/em&gt; who love caching but can’t agree on when to wake up:&lt;br&gt;
&lt;strong&gt;ISR (Incremental Static Regeneration)&lt;/strong&gt; and &lt;strong&gt;SSG (Static Site Generation)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Grab your coffee — this one’s about &lt;em&gt;performance, laziness, and SEO guilt.&lt;/em&gt; ☕&lt;/p&gt;


&lt;h2&gt;
  
  
  🏕️ First, SSG — The Overachiever Who Never Changes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt; means your pages are generated &lt;strong&gt;at build time&lt;/strong&gt; — long before any user visits.&lt;/p&gt;

&lt;p&gt;Imagine you bake 1,000 muffins in the morning (HTML pages), and when people visit, you just hand them one.&lt;br&gt;
Fast, efficient, and no stress. 🍰&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# next.config.js&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;async &lt;span class="k"&gt;function &lt;/span&gt;getStaticProps&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const posts &lt;span class="o"&gt;=&lt;/span&gt; await getAllPosts&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; props: &lt;span class="o"&gt;{&lt;/span&gt; posts &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you deploy, all your pages are ready-made HTML.&lt;br&gt;
Your CDN loves you, your users love you, and your backend server is asleep.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightning-fast load times (no server rendering at runtime)&lt;/li&gt;
&lt;li&gt;Cheap hosting (CDN handles it)&lt;/li&gt;
&lt;li&gt;Great SEO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to rebuild to update data&lt;/li&gt;
&lt;li&gt;Large sites = long build times&lt;/li&gt;
&lt;li&gt;Feels outdated if your data changes often (e.g., news, stock prices, or your mood)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  ⏰ Then, ISR — The Lazy Genius Who Updates Later
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Incremental Static Regeneration (ISR)&lt;/strong&gt; is like SSG’s chill cousin who says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hey, what if I don’t rebuild &lt;em&gt;everything&lt;/em&gt;, just the stuff that changed?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of regenerating all pages every time, &lt;strong&gt;ISR&lt;/strong&gt; allows static pages to &lt;strong&gt;update on demand&lt;/strong&gt; — after deployment.&lt;/p&gt;

&lt;p&gt;Example with Next.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;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;getStaticProps&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;data&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;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// re-generate this page every 60 seconds&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;That &lt;code&gt;revalidate: 60&lt;/code&gt; line?&lt;br&gt;
It’s like setting a reminder:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Yo server, refresh this page once a minute — but only if someone visits.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So your content stays fresh without full rebuilds.&lt;br&gt;
Basically, ISR is &lt;em&gt;lazy but responsible.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Still static (fast)&lt;/li&gt;
&lt;li&gt;Auto-refreshes data (SEO-friendly)&lt;/li&gt;
&lt;li&gt;Scales like a champ&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stale data between regenerations&lt;/li&gt;
&lt;li&gt;Slight delay on the first re-render&lt;/li&gt;
&lt;li&gt;Debugging can be... spiritually challenging&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚔️ ISR vs SSG — The Epic Face-Off
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;SSG&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;ISR&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Page generation&lt;/td&gt;
&lt;td&gt;Build time&lt;/td&gt;
&lt;td&gt;On-demand (after deploy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;⚡ Instant&lt;/td&gt;
&lt;td&gt;⚡ Still instant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data freshness&lt;/td&gt;
&lt;td&gt;🧊 Frozen in time&lt;/td&gt;
&lt;td&gt;🧃 Refreshes automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build time&lt;/td&gt;
&lt;td&gt;🐢 Can be long&lt;/td&gt;
&lt;td&gt;🚀 Much faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ideal for&lt;/td&gt;
&lt;td&gt;Blogs, docs, marketing pages&lt;/td&gt;
&lt;td&gt;News sites, product catalogs, dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSG&lt;/strong&gt;: “I did all my work before anyone came.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISR&lt;/strong&gt;: “I’ll update when I feel like it.”&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧙‍♂️ When to Use Which
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use SSG&lt;/strong&gt; when:&lt;br&gt;
You have stable content (blog posts, docs, landing pages).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use ISR&lt;/strong&gt; when:&lt;br&gt;
You want fast pages &lt;em&gt;and&lt;/em&gt; occasional freshness (product listings, blog homepages, event calendars).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don’t use either&lt;/strong&gt; when:&lt;br&gt;
Your data changes every few seconds — use &lt;strong&gt;SSR&lt;/strong&gt; or &lt;strong&gt;Edge Rendering&lt;/strong&gt; instead (coming in Episode 3 😏).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Real-World Example
&lt;/h2&gt;

&lt;p&gt;Let’s say you’re building a sneaker site.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The homepage and about page? → &lt;strong&gt;SSG&lt;/strong&gt; (they rarely change).&lt;/li&gt;
&lt;li&gt;The product listing page? → &lt;strong&gt;ISR&lt;/strong&gt;, so new sneakers appear automatically.&lt;/li&gt;
&lt;li&gt;The checkout page? → Definitely &lt;strong&gt;SSR&lt;/strong&gt;, because it depends on user sessions and inventory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Boom 💥 — hybrid architecture, modern as your favorite JS meme.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSG&lt;/strong&gt; = Build once, serve forever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISR&lt;/strong&gt; = Build once, revalidate sometimes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSR&lt;/strong&gt; = Build every time, if you hate caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSR&lt;/strong&gt; = Build nothing on the server, let the browser suffer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your app content rarely changes → &lt;strong&gt;SSG.&lt;/strong&gt;&lt;br&gt;
If it changes often → &lt;strong&gt;ISR.&lt;/strong&gt;&lt;br&gt;
If you like chaos → &lt;strong&gt;CSR + random API calls.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  😂 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;ISR and SSG aren’t enemies — they’re just different levels of caffeine tolerance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSG&lt;/strong&gt; is that person who wakes up at 5 AM and finishes all their work before breakfast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISR&lt;/strong&gt; wakes up at noon, updates stuff when necessary, and still gets great results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And both are still faster than your typical “Loading…” spinner built with pure CSR.&lt;/p&gt;




&lt;p&gt;Next time on &lt;strong&gt;Frontend Wars&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧩 &lt;em&gt;Hydration Hell — Why React Yells at You After SSR (and how to survive it with your sanity intact).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don’t miss it. Hydration errors are like mosquitoes — tiny but ruin your whole evening.&lt;/p&gt;




</description>
      <category>frontend</category>
      <category>architecture</category>
      <category>nextjs</category>
      <category>performance</category>
    </item>
    <item>
      <title>SSR vs CSR: Why Your Website Loads Like a Potato (and How to Fix It)</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Mon, 13 Oct 2025 18:38:05 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/ssr-vs-csr-why-your-website-loads-like-a-potato-and-how-to-fix-it-1bo</link>
      <guid>https://dev.to/lucasbrdt268/ssr-vs-csr-why-your-website-loads-like-a-potato-and-how-to-fix-it-1bo</guid>
      <description>&lt;p&gt;Let’s be honest — we’ve all been there. You open your web app, and instead of your beautiful UI, you get... a blank white screen and a spinning loader doing absolutely nothing.&lt;/p&gt;

&lt;p&gt;That’s when you realize:&lt;br&gt;
You’ve fallen into the &lt;strong&gt;CSR trap&lt;/strong&gt; 😭&lt;/p&gt;

&lt;p&gt;But don’t worry — today we’ll talk about &lt;strong&gt;SSR vs CSR&lt;/strong&gt; (Server-Side Rendering vs Client-Side Rendering), why your website might load slower than dial-up internet, and how to make it &lt;em&gt;not potato-level slow&lt;/em&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🍳 First, what’s CSR?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Client-Side Rendering&lt;/strong&gt; means your browser downloads an empty HTML shell, then runs a giant JavaScript bundle to build everything.&lt;/p&gt;

&lt;p&gt;Sounds cool, until your user’s laptop fan starts screaming louder than your production alerts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- CSR HTML --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/bundle.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically, your server says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hey, here’s a box. I’ll send you the tools, now you build the house yourself.”&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;ul&gt;
&lt;li&gt;Great for SPAs (Single Page Apps).&lt;/li&gt;
&lt;li&gt;Smooth navigation after initial load.&lt;/li&gt;
&lt;li&gt;No full-page reloads.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Slow first load. (The potato part.)&lt;/li&gt;
&lt;li&gt;Bad SEO unless you jump through hoops.&lt;/li&gt;
&lt;li&gt;Users stare at a blank screen while JS downloads.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Now, SSR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Server-Side Rendering&lt;/strong&gt; means your server does the building work — it sends ready-made HTML to the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- SSR HTML --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome back, Lucas!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the page lands, the user &lt;strong&gt;instantly sees content&lt;/strong&gt;, even before JavaScript runs.&lt;br&gt;
(Like walking into a restaurant and finding your food already served 😋)&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Fast first load, great SEO.&lt;/li&gt;
&lt;li&gt;Instant content visibility.&lt;/li&gt;
&lt;li&gt;Works even if JS breaks (kinda).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;More load on the server.&lt;/li&gt;
&lt;li&gt;Slower navigation between pages (unless hydrated).&lt;/li&gt;
&lt;li&gt;Tricky caching + deployment setups.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚔️ SSR vs CSR: The Battle of the Decade
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;SSR&lt;/th&gt;
&lt;th&gt;CSR&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First Load Speed&lt;/td&gt;
&lt;td&gt;⚡ Fast&lt;/td&gt;
&lt;td&gt;🥔 Slow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEO&lt;/td&gt;
&lt;td&gt;🕵️‍♂️ Excellent&lt;/td&gt;
&lt;td&gt;😬 Needs help&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server Load&lt;/td&gt;
&lt;td&gt;💪 Heavy&lt;/td&gt;
&lt;td&gt;😎 Light&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User Interactions&lt;/td&gt;
&lt;td&gt;🔄 Slightly slower&lt;/td&gt;
&lt;td&gt;💨 Super smooth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complexity&lt;/td&gt;
&lt;td&gt;🧩 Medium&lt;/td&gt;
&lt;td&gt;😐 Simple(ish)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSR&lt;/strong&gt; = your app wakes up ready for work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSR&lt;/strong&gt; = your app needs 5 minutes and 2 coffees before loading.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧙‍♂️ The Hybrid Magic: SSR + CSR = ❤️
&lt;/h2&gt;

&lt;p&gt;Modern frameworks (Next.js, Nuxt, Remix) said,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Why not both?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They let you &lt;strong&gt;render pages on the server&lt;/strong&gt;, then &lt;strong&gt;hydrate&lt;/strong&gt; them in the browser — so your app feels instant and interactive.&lt;/p&gt;

&lt;p&gt;This hybrid is called &lt;strong&gt;Universal Rendering&lt;/strong&gt; or &lt;strong&gt;Hydration&lt;/strong&gt; (aka “The Holy Grail of Web Dev”).&lt;/p&gt;

&lt;p&gt;So your page loads fast &lt;em&gt;and&lt;/em&gt; feels like a SPA. Everyone wins — except your dev ops, who now have to deploy Node servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CSR&lt;/strong&gt; → Great for dashboards, bad for SEO.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSR&lt;/strong&gt; → Great for landing pages, heavier on the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid (Next.js)&lt;/strong&gt; → Great balance, and makes you look smart in meetings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your users need instant content → go SSR.&lt;br&gt;
If your users stay long and click around → CSR might be fine.&lt;br&gt;
If you want to impress your PM → just say “Next.js with hybrid rendering.” 😎&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;In the end, &lt;strong&gt;SSR vs CSR&lt;/strong&gt; isn’t a fight — it’s a balance.&lt;br&gt;
Like choosing between pizza and sushi.&lt;br&gt;
Both are delicious, it just depends on the mood (and the project).&lt;/p&gt;

&lt;p&gt;So next time your app loads like a potato, ask yourself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is my rendering strategy lazy, or am &lt;em&gt;I&lt;/em&gt; just pretending SSR is ‘too complex’ again?”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;✍️ &lt;strong&gt;Your turn:&lt;/strong&gt;&lt;br&gt;
What’s your worst “SSR/CSR nightmare”?&lt;br&gt;
Drop a story in the comments — I’ll bring popcorn 🍿&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Building a Webhook Listener with Node.js (Step-by-Step Guide)</title>
      <dc:creator>lucas-brdt268</dc:creator>
      <pubDate>Sun, 28 Sep 2025 15:18:55 +0000</pubDate>
      <link>https://dev.to/lucasbrdt268/building-a-webhook-listener-with-nodejs-step-by-step-guide-3ai5</link>
      <guid>https://dev.to/lucasbrdt268/building-a-webhook-listener-with-nodejs-step-by-step-guide-3ai5</guid>
      <description>&lt;p&gt;Webhooks power modern integrations — whether it’s receiving payment notifications from Stripe, alerts from GitHub, or messages from Slack. Instead of constantly polling an API, you let the service &lt;strong&gt;push&lt;/strong&gt; events to your app in real time.&lt;/p&gt;

&lt;p&gt;In this post, we’ll build a simple &lt;strong&gt;webhook listener&lt;/strong&gt; using &lt;strong&gt;Node.js + Express&lt;/strong&gt;. By the end, you’ll know how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand what a webhook is&lt;/li&gt;
&lt;li&gt;Set up a webhook endpoint in Node.js&lt;/li&gt;
&lt;li&gt;Parse and log incoming events&lt;/li&gt;
&lt;li&gt;Test your webhook locally with Ngrok&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧩 What is a Webhook?
&lt;/h2&gt;

&lt;p&gt;A webhook is just an &lt;strong&gt;HTTP callback&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A service sends an HTTP request (usually &lt;code&gt;POST&lt;/code&gt;) to your app when something happens.&lt;/li&gt;
&lt;li&gt;Your app receives that request, processes it, and responds.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;GitHub → sends a &lt;code&gt;POST /webhook&lt;/code&gt; with info about a new pull request&lt;/li&gt;
&lt;li&gt;Your app → logs the event or triggers another process&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Step 1. Setup Project
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;node-webhook-listener
&lt;span class="nb"&gt;cd &lt;/span&gt;node-webhook-listener
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;express body-parser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚡ Step 2. Create Express Server
&lt;/h2&gt;

&lt;p&gt;Create a file: &lt;strong&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&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;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body-parser&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&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;PORT&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;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Middleware to parse JSON&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&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="c1"&gt;// Webhook endpoint&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/webhook&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;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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;📩 Webhook received:&lt;/span&gt;&lt;span class="dl"&gt;'&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;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Always reply with 200 OK so the sender knows you got it&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Webhook received&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🚀 Server is running on http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚡ Step 3. Test Locally with Ngrok
&lt;/h2&gt;

&lt;p&gt;External services can’t reach &lt;code&gt;localhost&lt;/code&gt;, so we need to expose it with &lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;Ngrok&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx ngrok http 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ngrok will give you a public URL, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://abc123.ngrok.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you send a webhook to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://abc123.ngrok.io/webhook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will forward it to your local server. 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Step 4. Send a Test Request
&lt;/h2&gt;

&lt;p&gt;You can simulate an external webhook using &lt;code&gt;curl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://abc123.ngrok.io/webhook &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"event":"order.created","data":{"id":123,"amount":500}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your terminal — you should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📩 Webhook received: { event: 'order.created', data: { id: 123, amount: 500 } }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛡️ (Optional) Step 5. Secure Your Webhook
&lt;/h2&gt;

&lt;p&gt;Most services sign webhook payloads with a secret. You should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify the signature (HMAC)&lt;/li&gt;
&lt;li&gt;Only accept requests from trusted sources&lt;/li&gt;
&lt;li&gt;Avoid logging sensitive data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(We’ll dive deeper into webhook security in another post 👀)&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Wrap Up
&lt;/h2&gt;

&lt;p&gt;We just built a basic &lt;strong&gt;webhook listener&lt;/strong&gt; in Node.js:&lt;/p&gt;

&lt;p&gt;✅ Express server with &lt;code&gt;/webhook&lt;/code&gt; endpoint&lt;br&gt;
✅ Logging incoming events&lt;br&gt;
✅ Local testing with Ngrok&lt;br&gt;
✅ Ready to integrate with APIs like Stripe, GitHub, or Slack&lt;/p&gt;

&lt;p&gt;Next steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;strong&gt;signature verification&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Connect the webhook events to your app’s logic&lt;/li&gt;
&lt;li&gt;Deploy to a cloud service&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;👉 What services are you planning to integrate with webhooks? Let me know in the comments!&lt;/p&gt;

</description>
      <category>backend</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
