<?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: Sachin Maurya</title>
    <description>The latest articles on DEV Community by Sachin Maurya (@maurya-sachin).</description>
    <link>https://dev.to/maurya-sachin</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%2F1046037%2F27ffba04-9465-46ab-84bb-50236e7e309e.png</url>
      <title>DEV Community: Sachin Maurya</title>
      <link>https://dev.to/maurya-sachin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maurya-sachin"/>
    <language>en</language>
    <item>
      <title>Building a Multi-Layer Caching Strategy in Next.js App Router: From Static to Real-Time</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Thu, 01 Jan 2026 05:29:06 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/building-a-multi-layer-caching-strategy-in-nextjs-app-router-from-static-to-real-time-4che</link>
      <guid>https://dev.to/maurya-sachin/building-a-multi-layer-caching-strategy-in-nextjs-app-router-from-static-to-real-time-4che</guid>
      <description>&lt;p&gt;Caching is one of those make-or-break aspects of modern web development. Get it right, and your app is fast, resilient, and scalable. Get it wrong, and you’re left with stale data, poor performance, or worse — broken user experiences.&lt;/p&gt;

&lt;p&gt;At my previous role, I led the migration of our corporate platform to the Next.js App Router. One of our core challenges was designing a caching strategy that could handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fully static marketing pages
&lt;/li&gt;
&lt;li&gt;Occasionally updated blog content
&lt;/li&gt;
&lt;li&gt;Personalized user dashboards
&lt;/li&gt;
&lt;li&gt;Real-time activity feeds
&lt;/li&gt;
&lt;li&gt;Mixed-content pages (static + dynamic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, I’ll walk through how we built a &lt;strong&gt;multi-layer caching architecture&lt;/strong&gt; that kept our Lighthouse scores consistently above 95 while ensuring data freshness where it mattered most.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Next.js Caching Layers
&lt;/h2&gt;

&lt;p&gt;Before jumping into implementation, it’s important to understand the caching layers available in the App Router:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Full Route Cache&lt;/strong&gt; – Entire route responses (HTML) cached at build or request time
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Cache&lt;/strong&gt; – Results of &lt;code&gt;fetch&lt;/code&gt; requests persisted across requests
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Cache&lt;/strong&gt; – Caching done in the browser (via React Query, Zustand, etc.)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDN/Edge Cache&lt;/strong&gt; – Caching at the network edge (Vercel, Cloudflare, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each layer serves a different purpose, and using them together is key.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1: Fully Static Pages with &lt;code&gt;force-static&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We had several pages that never changed: &lt;code&gt;/about&lt;/code&gt;, &lt;code&gt;/contact&lt;/code&gt;, &lt;code&gt;/legal&lt;/code&gt;. For these, we used:&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;// app/about/page.js&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;dynamic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;force-static&lt;/span&gt;&lt;span class="dl"&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;AboutPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// This page is cached at build time&lt;/span&gt;
  &lt;span class="c1"&gt;// and served from CDN indefinitely&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why &lt;code&gt;force-static&lt;/code&gt;?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It tells Next.js to skip all dynamic logic, treat the page as completely static, and cache it at the edge. This is ideal for true static content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
These pages loaded instantly on repeat visits and required zero backend computation.&lt;/p&gt;


&lt;h2&gt;
  
  
  Layer 2: Incrementally Static Pages with ISR
&lt;/h2&gt;

&lt;p&gt;Our blog and documentation pages were mostly static but could be updated via CMS. We used &lt;strong&gt;Incremental Static Regeneration (ISR)&lt;/strong&gt; with on-demand revalidation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1 – Basic ISR
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/blog/[slug]/page.js&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;revalidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="c1"&gt;// Revalidate every hour&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;getPost&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="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="s2"&gt;`https://api.example.com/posts/&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&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;return&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="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;BlogPost&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;getPost&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PostLayout&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="o"&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&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 – On-Demand Revalidation
&lt;/h3&gt;

&lt;p&gt;When a post was updated in the CMS, we triggered:&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;// app/api/revalidate/route.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;revalidateTag&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/cache&lt;/span&gt;&lt;span class="dl"&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;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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;tag&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nf"&gt;revalidateTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// e.g., 'posts'&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;This meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blog posts were cached for performance&lt;/li&gt;
&lt;li&gt;But could be updated in seconds when needed&lt;/li&gt;
&lt;li&gt;No full rebuilds required&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Layer 3: Personalized Dashboards – No Server Cache
&lt;/h2&gt;

&lt;p&gt;For authenticated user dashboards (&lt;code&gt;/dashboard&lt;/code&gt;, &lt;code&gt;/settings&lt;/code&gt;), we disabled server caching entirely.&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;// app/dashboard/page.js&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;dynamic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;force-dynamic&lt;/span&gt;&lt;span class="dl"&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;DashboardPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// This page is never cached on the server&lt;/span&gt;
  &lt;span class="c1"&gt;// Fresh data on every request&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, we moved caching to the &lt;strong&gt;client layer&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React Query&lt;/strong&gt; for server-state caching, background updates, and request deduplication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zustand&lt;/strong&gt; for client-side UI state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimistic updates&lt;/strong&gt; for a snappy UX&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example with React Query:&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;// app/dashboard/activity.js&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchActivity&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="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;/api/activity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;ActivityFeed&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;activity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetchActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;staleTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Consider data fresh for 5 minutes&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="c1"&gt;// Render feed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why client cache here?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
User data is personalized and sensitive. Server caching could leak data between users. Client caching is safe and still provides performance benefits.&lt;/p&gt;


&lt;h2&gt;
  
  
  Layer 4: Real-Time Components with Streaming
&lt;/h2&gt;

&lt;p&gt;For real-time components like live notifications or stats, we used &lt;strong&gt;Streaming with Suspense&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Component Structure
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/dashboard/live-stats.js&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="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;LiveStats&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;stats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStats&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://api.example.com/live&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setStats&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;stats&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;StatCard&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt; : &amp;lt;StatSkeleton /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Wrapping in Suspense
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/dashboard/page.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;LiveStats&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./live-stats&lt;/span&gt;&lt;span class="dl"&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;Dashboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Dashboard&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;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StatSkeleton&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LiveStats&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="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This allowed the rest of the page to load quickly while real-time components hydrated separately.&lt;/p&gt;


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

&lt;p&gt;Our homepage was tricky:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static hero section
&lt;/li&gt;
&lt;li&gt;Dynamic user greeting (if logged in)
&lt;/li&gt;
&lt;li&gt;Real-time trending section
&lt;/li&gt;
&lt;li&gt;Cached blog previews&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Our Solution: Isolate Caching Boundaries
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/page.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getHeroData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getTrendingPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/app/actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserGreeting&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user-greeting&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;TrendingSection&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./trending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;BlogPreview&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blog-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Cache static data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getCachedHeroData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getHeroData&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;getCachedTrending&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getTrendingPosts&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;HomePage&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;heroData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;trending&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nf"&gt;getCachedHeroData&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;getCachedTrending&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Static hero */&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;Hero&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;heroData&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Dynamic user greeting */&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;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GreetingSkeleton&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserGreeting&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="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Real-time trending */&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;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TrendingSkeleton&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TrendingSection&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="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Cached blog previews */&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;BlogPreview&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;trending&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&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;By splitting sections into different caching boundaries, we optimized each part independently.&lt;/p&gt;


&lt;h2&gt;
  
  
  Monitoring &amp;amp; Debugging
&lt;/h2&gt;

&lt;p&gt;A caching strategy is useless without monitoring.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Lighthouse + Web Vitals
&lt;/h3&gt;

&lt;p&gt;We ran Lighthouse in CI on every PR and set performance budgets.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Custom Cache Logging
&lt;/h3&gt;

&lt;p&gt;We added logging middleware to track cache hits/misses:&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;// middleware.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Add cache headers for static assets&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/_next/static&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cache-Control&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public, max-age=31536000, immutable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Vercel Analytics
&lt;/h3&gt;

&lt;p&gt;We used Vercel’s built-in analytics to monitor cache hit ratios and edge performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Results &amp;amp; Metrics
&lt;/h2&gt;

&lt;p&gt;After implementing this layered approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lighthouse Performance:&lt;/strong&gt; 96+ (consistent across pages)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache Hit Ratio (CDN):&lt;/strong&gt; 92%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Backend Load:&lt;/strong&gt; ~40% fewer queries for cached content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time to Interactive:&lt;/strong&gt; Improved by ~35%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Updates:&lt;/strong&gt; Reflected within 2-3 seconds&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cache based on content type, not convenience&lt;/strong&gt; – Each type of content has different freshness requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;revalidateTag&lt;/code&gt; over &lt;code&gt;revalidatePath&lt;/code&gt;&lt;/strong&gt; – More precise, less expensive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client caching is not obsolete&lt;/strong&gt; – It’s essential for personalized data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor, monitor, monitor&lt;/strong&gt; – Caching behavior can change with traffic patterns and updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document your strategy&lt;/strong&gt; – Team onboarding and debugging become much easier.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;Caching in the App Router is powerful but requires intentional design. There’s no one-size-fits-all solution. By building a &lt;strong&gt;multi-layer caching strategy&lt;/strong&gt;, you can optimize for both performance and freshness.&lt;/p&gt;

&lt;p&gt;If you’re working on a Next.js app and thinking about caching, start by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Auditing your content types&lt;/strong&gt; – What’s static? What’s dynamic?
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mapping content to cache layers&lt;/strong&gt; – Use the right tool for each job.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementing incrementally&lt;/strong&gt; – Start with static pages, then add ISR, then client caching.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measuring impact&lt;/strong&gt; – Use Lighthouse and analytics to validate improvements.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Caching isn’t just a performance optimization—it’s a core part of your application architecture. Design it thoughtfully, and your users (and your infrastructure) will thank you.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Interested in more deep dives on Next.js performance?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Check out my other posts on &lt;a href="https://dev.to/maurya-sachin/the-cost-of-re-renders-how-to-make-react-apps-actually-reactive-3mc6"&gt;React re-renders&lt;/a&gt;, &lt;a href="https://dev.to/maurya-sachin/reducing-javascript-bundle-size-in-nextjs-practical-guide-for-faster-apps-h0"&gt;bundle optimization&lt;/a&gt;, and &lt;a href="https://dev.to/maurya-sachin/wcag-21-complete-guide-for-developers-practical-tips-from-real-audits-3l35"&gt;WCAG compliance&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>A More Structured Version of Frontend Master Prep Series</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Fri, 12 Dec 2025 14:49:04 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/a-more-structured-version-of-frontend-master-prep-series-1300</link>
      <guid>https://dev.to/maurya-sachin/a-more-structured-version-of-frontend-master-prep-series-1300</guid>
      <description>&lt;p&gt;I’ve updated the Frontend Master Prep Series with a focus on structure and clarity rather than adding more questions or problems.&lt;/p&gt;

&lt;p&gt;The earlier versions of the repo were useful, but not very guided. There wasn’t a clear sense of where to begin, how to move through topics, or how the Q&amp;amp;A, challenges, and flashcards were meant to work together. This update focuses on solving that.&lt;/p&gt;

&lt;p&gt;The README now includes three specific starting points:&lt;br&gt;
• A four-week study plan for anyone preparing with a defined timeline&lt;br&gt;
• A daily practice flow that combines flashcards and coding problems&lt;br&gt;
• A short, focused revision checklist for last-minute preparation&lt;/p&gt;

&lt;p&gt;The internal structure is now more intentional. Each topic has its own place, and Q&amp;amp;A, examples, and flashcards are no longer mixed together. The architecture section is also separated out so it can grow without affecting the rest of the repo.&lt;/p&gt;

&lt;p&gt;The flashcards have been updated as well. They now work in both Markdown and the interactive version of the app, which uses spaced repetition and tracks progress locally.&lt;/p&gt;

&lt;p&gt;Coding problems remain at 65 for now, but the grouping and purpose are clearer. They are organized by theme and difficulty instead of being a loose collection.&lt;/p&gt;

&lt;p&gt;This update is mainly about usability. The goal is to make the repo something developers can return to regularly, whether they are revising fundamentals or preparing for interviews.&lt;/p&gt;

&lt;p&gt;The repo is here if you want to explore the structure:&lt;br&gt;
&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;https://github.com/maurya-sachin/Frontend-Master-Prep-Series&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>learning</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>I just shipped v3.0 of Frontend Master Prep Series — Study Paths, 374+ Q&amp;A, 65 Coding Problems &amp; 500+ Flashcards</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Fri, 28 Nov 2025 05:14:21 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/i-just-shipped-v30-of-frontend-master-prep-series-study-paths-374-qa-65-coding-problems--44mi</link>
      <guid>https://dev.to/maurya-sachin/i-just-shipped-v30-of-frontend-master-prep-series-study-paths-374-qa-65-coding-problems--44mi</guid>
      <description>&lt;p&gt;A while back, I shared two big milestones in my frontend prep journey:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A list of 650+ frontend interview questions&lt;/strong&gt; — the raw brain-dump that started it all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v2.0 of Frontend Master Prep Series&lt;/strong&gt; — where that list evolved into a more structured “frontend mastery system.”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since then, the repo has kept growing — but more importantly, &lt;strong&gt;how you use it&lt;/strong&gt; has changed.&lt;/p&gt;

&lt;p&gt;Developers didn’t just want &lt;em&gt;more&lt;/em&gt; content.&lt;br&gt;
They wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear &lt;strong&gt;entry points&lt;/strong&gt; (What do I do if my interview is tomorrow vs in 4 weeks?)&lt;/li&gt;
&lt;li&gt;A way to &lt;strong&gt;revise quickly&lt;/strong&gt; without scrolling through massive markdown files&lt;/li&gt;
&lt;li&gt;A path that feels like a &lt;strong&gt;learning system&lt;/strong&gt;, not just a massive question bank&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So v3.0 is all about that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Less “here are a thousand things you could read.”&lt;br&gt;
More “here’s exactly how to use this to get better, fast.”&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  What’s new in v3.0?
&lt;/h2&gt;

&lt;p&gt;Here’s what this release focuses on.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Guided Quick Start paths
&lt;/h3&gt;

&lt;p&gt;The README now starts with &lt;strong&gt;four clear ways to begin&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;4-Week Sprint&lt;/strong&gt; → A complete study plan for people targeting interviews in a month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interview Tomorrow?&lt;/strong&gt; → A 30-card flashcard deck for last-minute revision&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Practice&lt;/strong&gt; → A consistent routine with Essential 50 + coding problems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Study&lt;/strong&gt; → A flashcard web app you can open in your browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of wondering &lt;em&gt;“Where do I start?”&lt;/em&gt;, you pick the path that fits your timeline and dive in. (&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/p&gt;


&lt;h3&gt;
  
  
  2. A cleaner content model (with real numbers)
&lt;/h3&gt;

&lt;p&gt;The repo is now explicitly framed around &lt;strong&gt;three pillars&lt;/strong&gt;:&lt;/p&gt;
&lt;h4&gt;
  
  
  ✅ Core Q&amp;amp;A
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;374+ Q&amp;amp;A&lt;/strong&gt; across &lt;strong&gt;16 topics&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;JavaScript, TypeScript, React, Next.js, HTML/CSS, Testing, Performance, Accessibility, Security, System Design, Browser, Networking, PWA, Tooling, i18n, SEO&lt;/li&gt;
&lt;li&gt;Each with explanations, follow-up questions, mistakes, and real-world context (&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the “deep reading + understanding” layer.&lt;/p&gt;
&lt;h4&gt;
  
  
  ✅ Coding Problems
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;65 problems&lt;/strong&gt; live right now, targeting &lt;strong&gt;185+&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Categories: JS fundamentals, DOM, React problems, algorithms, UI components, system implementations, company-style questions&lt;/li&gt;
&lt;li&gt;Each problem aims to include: multiple solution approaches, tests, complexity, and real-world use cases (&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where you move from &lt;em&gt;knowing&lt;/em&gt; to &lt;em&gt;doing&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  ✅ Flashcards + Web App
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;514+ flashcards&lt;/strong&gt; spread across curated decks and topic decks&lt;/li&gt;
&lt;li&gt;Curated decks like &lt;strong&gt;Essential 50&lt;/strong&gt;, &lt;strong&gt;Pre-Interview 30&lt;/strong&gt;, &lt;strong&gt;Daily Review 20&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Topic decks for JS, React, TS, Next.js, HTML/CSS, Performance, etc.(&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Two formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markdown (for GitHub / Obsidian / VS Code)&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;interactive React app&lt;/strong&gt; with spaced repetition (SM-2), local storage, and progress tracking&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is your “maintenance mode” — keeping your brain warm daily.&lt;/p&gt;


&lt;h3&gt;
  
  
  3. A dev-friendly, scalable structure
&lt;/h3&gt;

&lt;p&gt;One big change in v3.0 is treating the repo &lt;strong&gt;like a real product&lt;/strong&gt;, not just a folder of notes.&lt;/p&gt;

&lt;p&gt;Here’s the updated structure straight from the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Frontend-Master-Prep-Series/
├── 01-javascript/          &lt;span class="c"&gt;# Core JS concepts, async, engine internals (53 files)&lt;/span&gt;
├── 02-typescript/          &lt;span class="c"&gt;# Type system, generics, advanced patterns (22 files)&lt;/span&gt;
├── 03-react/               &lt;span class="c"&gt;# Hooks, patterns, performance, internals (71 files)&lt;/span&gt;
├── 04-nextjs/              &lt;span class="c"&gt;# App Router, SSR, ISR, Server Components (16 files)&lt;/span&gt;
├── 05-html-css/            &lt;span class="c"&gt;# Semantics, layouts, modern CSS (19 files)&lt;/span&gt;
├── 06-testing/             &lt;span class="c"&gt;# Jest, RTL, E2E, testing patterns (5 files)&lt;/span&gt;
├── 07-performance/         &lt;span class="c"&gt;# Core Web Vitals, optimization (6 files)&lt;/span&gt;
├── 08-accessibility/       &lt;span class="c"&gt;# WCAG, ARIA, keyboard navigation (17 files)&lt;/span&gt;
├── 09-security/            &lt;span class="c"&gt;# XSS, CSRF, auth, headers (6 files - expanding)&lt;/span&gt;
├── 10-system-design/       &lt;span class="c"&gt;# Component &amp;amp; frontend design patterns (4 files)&lt;/span&gt;
├── 11-browser/             &lt;span class="c"&gt;# Rendering pipeline, storage APIs (3 files)&lt;/span&gt;
├── 12-networking/          &lt;span class="c"&gt;# HTTP/2/3, caching, CDNs (3 files)&lt;/span&gt;
├── 13-pwa/                 &lt;span class="c"&gt;# Service workers, offline-first (3 files)&lt;/span&gt;
├── 14-tooling/             &lt;span class="c"&gt;# Webpack, Vite, Babel (3 files)&lt;/span&gt;
├── 15-i18n/                &lt;span class="c"&gt;# Localization, RTL, formatting (3 files)&lt;/span&gt;
├── 16-architecture/        &lt;span class="c"&gt;# Coming soon - frontend architecture patterns&lt;/span&gt;
├── 17-seo/                 &lt;span class="c"&gt;# Technical SEO, structured data (2 files)&lt;/span&gt;
├── 18-coding-challenges/   &lt;span class="c"&gt;# 65 coding problems&lt;/span&gt;
│   ├── 01-javascript-fundamentals/
│   ├── 02-dom-manipulation/
│   ├── 03-react-problems/
│   ├── 04-algorithms/
│   ├── 05-ui-components/
│   └── 06-performance/
├── 19-flashcards/          &lt;span class="c"&gt;# 514+ flashcards&lt;/span&gt;
│   ├── curated-decks/
│   └── by-topic/
├── src/                    &lt;span class="c"&gt;# Flashcard web app (React + Vite)&lt;/span&gt;
├── public/                 &lt;span class="c"&gt;# Static assets, manifest&lt;/span&gt;
└── resources/              &lt;span class="c"&gt;# Study guides, checklists, learning paths&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is intentional: if someone clones the repo, they immediately understand &lt;strong&gt;where everything lives&lt;/strong&gt; and how to extend it.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Study paths baked into the README
&lt;/h3&gt;

&lt;p&gt;You no longer have to invent your own plan.&lt;/p&gt;

&lt;p&gt;The README now includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;4-week sprint plan&lt;/strong&gt; (week-by-week focus + time estimates)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Daily Practice path&lt;/strong&gt; for long-term growth&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;“Interview Tomorrow?” checklist&lt;/strong&gt; that tells you exactly what to hit in 30–60 minutes (&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the repo usable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Panic revision&lt;/li&gt;
&lt;li&gt;Structured, medium-term prep&lt;/li&gt;
&lt;li&gt;Slow, consistent mastery&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The GitHub repo
&lt;/h2&gt;

&lt;p&gt;👉 &lt;strong&gt;Frontend Master Prep Series v3&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;https://github.com/maurya-sachin/Frontend-Master-Prep-Series&lt;/a&gt; (&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Open it in VS Code, Obsidian, or straight in the browser.&lt;br&gt;
Use it as a reference, a study plan, or a daily practice system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this version matters
&lt;/h2&gt;

&lt;p&gt;The first post (650+ questions) was about &lt;strong&gt;volume&lt;/strong&gt;.&lt;br&gt;
The second one (v2.0) was about turning that volume into a &lt;strong&gt;mastery system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;v3.0 is different.&lt;/p&gt;

&lt;p&gt;This release is about &lt;strong&gt;experience&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How fast can you get from “I found this repo” to “I’m using it daily”?&lt;/li&gt;
&lt;li&gt;How easy is it to switch between reading, solving, and revising?&lt;/li&gt;
&lt;li&gt;Can you use it whether you have 10 minutes or 2 hours?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve tried to answer those questions with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear quick-start paths&lt;/li&gt;
&lt;li&gt;A predictable structure&lt;/li&gt;
&lt;li&gt;A flashcard app that actually respects how memory works&lt;/li&gt;
&lt;li&gt;Study plans you don’t have to design yourself&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;I’m actively working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filling out &lt;strong&gt;Architecture&lt;/strong&gt; and &lt;strong&gt;System Design&lt;/strong&gt; sections&lt;/li&gt;
&lt;li&gt;More &lt;strong&gt;company-style question sets&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Expanding &lt;strong&gt;React + Next.js patterns&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;More &lt;strong&gt;performance &amp;amp; networking case studies&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Potentially a &lt;strong&gt;Notion/Obsidian template&lt;/strong&gt; wired to this structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there’s something specific you’d like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A deck for a specific company?&lt;/li&gt;
&lt;li&gt;More problems in a certain category?&lt;/li&gt;
&lt;li&gt;A deep-dive on a topic inside this repo?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open an issue, comment on the repo, or ping me — I’m building this in public and your feedback genuinely shapes the roadmap.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I keep building this
&lt;/h2&gt;

&lt;p&gt;Honestly, I built this for myself first.&lt;/p&gt;

&lt;p&gt;I wanted to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stop prepping from scattered YouTube playlists and notes&lt;/li&gt;
&lt;li&gt;Have a single place that respects both &lt;strong&gt;interview prep&lt;/strong&gt; and &lt;strong&gt;real-world engineering&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Turn my own interview scars into something useful for other devs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If even one developer walks into their next interview a little more confident because of this repo, all the late-night organizing, refactoring, and writing has already paid off.&lt;/p&gt;




&lt;p&gt;⭐ If this helps you, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starring the repo&lt;/li&gt;
&lt;li&gt;Sharing it with a friend who’s prepping&lt;/li&gt;
&lt;li&gt;Sending feedback so v4.0 can be even better&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s make frontend interview prep feel less chaotic — and a lot more intentional.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
      <category>career</category>
    </item>
    <item>
      <title>The 7 Mistakes I Made as a Junior Frontend Developer (and the Engineering Fixes That Helped Me Grow Faster)</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Fri, 21 Nov 2025 17:00:34 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/the-7-mistakes-i-made-as-a-junior-frontend-developer-and-the-engineering-fixes-that-helped-me-grow-26ii</link>
      <guid>https://dev.to/maurya-sachin/the-7-mistakes-i-made-as-a-junior-frontend-developer-and-the-engineering-fixes-that-helped-me-grow-26ii</guid>
      <description>&lt;p&gt;Early in my frontend career, I wasn’t struggling because JavaScript was hard.&lt;br&gt;
I struggled because I didn’t understand &lt;em&gt;engineering thinking&lt;/em&gt;.&lt;br&gt;
Here are the mistakes that slowed me down — and the exact technical shifts that finally pushed me forward.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. Focusing on UI output instead of understanding the architecture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I used to write components quickly… and rewrite them even quicker when the project grew.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt;&lt;br&gt;
Frontend is architecture-heavy. Naming, data ownership, routing boundaries, API strategy, state placement — everything matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix in practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Co-located state with the smallest responsible component&lt;/li&gt;
&lt;li&gt;Used “feature-first” folder structure&lt;/li&gt;
&lt;li&gt;Adopted clear boundaries between server state (React Query) and UI state (Zustand/Context)&lt;/li&gt;
&lt;li&gt;Removed cross-feature imports to avoid spaghetti&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This alone made my codebases far more predictable.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. Copy–pasting solutions without understanding internals&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I solved problems fast, but only on the surface.&lt;br&gt;
Whenever something broke, I couldn't debug deeper because I never knew how it &lt;em&gt;actually&lt;/em&gt; worked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix in practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Studied the React reconciliation RFC&lt;/li&gt;
&lt;li&gt;Read how the browser event loop schedules microtasks vs macrotasks&lt;/li&gt;
&lt;li&gt;Explored how React Query caches and invalidates data&lt;/li&gt;
&lt;li&gt;Learned how Next.js handles RSC hydration boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reading internals gave me “X-ray vision” during debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. Treating performance as a final step instead of a design constraint&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I used to optimise only when Lighthouse screamed at me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix in practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Measured hydration cost and moved heavy UI to server components&lt;/li&gt;
&lt;li&gt;Reduced bundle size using dynamic imports + route-level code splitting&lt;/li&gt;
&lt;li&gt;Cached expensive calculations using &lt;code&gt;useMemo&lt;/code&gt; only where profiling proved it helped&lt;/li&gt;
&lt;li&gt;Added proper caching headers + ISR for API-heavy pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Performance improved because I designed with it in mind.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Over-engineering small features&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I thought adding abstraction made me “senior”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix in practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used reducers only for genuinely complex state transitions&lt;/li&gt;
&lt;li&gt;Avoided wrapper components when plain JSX worked&lt;/li&gt;
&lt;li&gt;Stopped making utility functions for one-line logic&lt;/li&gt;
&lt;li&gt;Followed the “start simple → scale when needed” rule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Removing unnecessary layers made my code easier to read and maintain.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5. Taking CSS lightly&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My layouts looked fine… until they broke on a different screen size or when content changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix in practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learned CSS cascade layers (huge mental unlock)&lt;/li&gt;
&lt;li&gt;Used logical properties for RTL-friendly layouts&lt;/li&gt;
&lt;li&gt;Adopted consistent spacing/typography tokens&lt;/li&gt;
&lt;li&gt;Designed components with intrinsic sizing first, not pixel-perfect assumptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CSS became less “trial and error” and more “predictable behaviour”.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6. Random learning with no system&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I bounced between tutorials, and it felt like progress… except nothing stuck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix in practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Followed a clear roadmap&lt;/li&gt;
&lt;li&gt;Built real projects instead of cloning UIs&lt;/li&gt;
&lt;li&gt;Took notes with examples, not theory&lt;/li&gt;
&lt;li&gt;Revised older codebases to see improvement clearly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structured approach finally created momentum.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;7. Ignoring accessibility until a real project forced me to care&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My mindset changed when I worked on a government project that &lt;em&gt;had&lt;/em&gt; to meet WCAG.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix in practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensured every interactive element was keyboard-first&lt;/li&gt;
&lt;li&gt;Used semantic markup before ARIA&lt;/li&gt;
&lt;li&gt;Tested with screen readers&lt;/li&gt;
&lt;li&gt;Checked contrast ratios and focus paths&lt;/li&gt;
&lt;li&gt;Avoided “div soup” that confuses assistive tech&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accessibility stopped being a checkbox; it became a performance and UX enhancer.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Why I Wrote This&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Every engineer grows through mistakes — but some mistakes slow the journey more than others.&lt;br&gt;
These were mine.&lt;br&gt;
If you're somewhere in this list, you’re not behind — you’re right where most of us started.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>html</category>
    </item>
    <item>
      <title>I just shipped v2.0 of Frontend Master Prep Series — 1,020+ Q&amp;A + 185 coding problems + 600 flashcards</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Mon, 10 Nov 2025 16:36:25 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/i-just-shipped-v20-of-frontend-master-prep-series-1020-qa-185-coding-problems-600-33j7</link>
      <guid>https://dev.to/maurya-sachin/i-just-shipped-v20-of-frontend-master-prep-series-1020-qa-185-coding-problems-600-33j7</guid>
      <description>&lt;p&gt;A few days back, I published a list of 650+ frontend interview questions.&lt;/p&gt;

&lt;p&gt;That post got attention, feedback, and a surprising amount of messages from developers (both junior and senior) telling me it helped them prep better.&lt;/p&gt;

&lt;p&gt;But something didn’t feel complete.&lt;/p&gt;

&lt;p&gt;Because questions alone are not enough.&lt;/p&gt;

&lt;p&gt;So I continued learning deeply, exploring each topic, facing more interviews, reading docs, breaking code, and then documenting the patterns I found.&lt;/p&gt;

&lt;p&gt;And that small side note list turned into something else completely.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s new in v2.0?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;1,020+ questions with detailed answers&lt;/li&gt;
&lt;li&gt;185+ coding problems (each solved step-by-step)&lt;/li&gt;
&lt;li&gt;600+ flashcards for fast revision&lt;/li&gt;
&lt;li&gt;new sections: TypeScript, Security, Testing, Tooling&lt;/li&gt;
&lt;li&gt;difficulty tags, interview frequency, company tags&lt;/li&gt;
&lt;li&gt;code examples + common mistakes + time to answer estimates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is no longer “a question bank”.&lt;br&gt;
This is a &lt;strong&gt;complete frontend mastery system&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Repo
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📘 Frontend Master Prep Series v2&lt;br&gt;
&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series" rel="noopener noreferrer"&gt;https://github.com/maurya-sachin/Frontend-Master-Prep-Series&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Open-source. Free. Well-structured.&lt;br&gt;
Use it in VS Code / Obsidian / Notion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Most interview prep content online is too shallow.&lt;/p&gt;

&lt;p&gt;It teaches the &lt;em&gt;what&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But senior interviews check the &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Why does React re-render?&lt;br&gt;
Why does this promise resolve later?&lt;br&gt;
Why Next.js instead of client-side React?&lt;/p&gt;

&lt;p&gt;This project grew because I kept asking that exact question myself.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;I’m currently working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a Notion version with progress tracking&lt;/li&gt;
&lt;li&gt;a PDF cheat sheet for 1-day revision&lt;/li&gt;
&lt;li&gt;a “Roadmap style” resource guide by topics&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;To be honest — I built this for myself first.&lt;br&gt;
Because I wanted to really understand this craft.&lt;/p&gt;

&lt;p&gt;But if even one developer somewhere uses this repo and gets more confident before their next interview —&lt;br&gt;
then this work is already worth it.&lt;/p&gt;




&lt;p&gt;If you find this useful — consider giving a ⭐ to the repo.&lt;br&gt;
That’s how I’ll know this should continue growing.&lt;/p&gt;




&lt;p&gt;tags: &lt;code&gt;frontend&lt;/code&gt; &lt;code&gt;react&lt;/code&gt; &lt;code&gt;nextjs&lt;/code&gt; &lt;code&gt;javascript&lt;/code&gt; &lt;code&gt;typescript&lt;/code&gt; &lt;code&gt;webdev&lt;/code&gt; &lt;code&gt;career&lt;/code&gt; &lt;code&gt;interviewprep&lt;/code&gt; &lt;code&gt;learning&lt;/code&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>career</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>650+ Frontend Interview Questions (JavaScript, React, Next.js &amp; More) — My Complete Prep Journey</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Sat, 01 Nov 2025 13:36:16 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/650-frontend-interview-questions-javascript-react-nextjs-more-my-complete-prep-journey-12in</link>
      <guid>https://dev.to/maurya-sachin/650-frontend-interview-questions-javascript-react-nextjs-more-my-complete-prep-journey-12in</guid>
      <description>&lt;p&gt;After giving a few frontend interviews recently, I noticed a pattern.&lt;/p&gt;

&lt;p&gt;Almost every interviewer went beyond surface-level coding questions and asked about how things actually work under the hood —&lt;br&gt;&lt;br&gt;
things like &lt;strong&gt;the event loop&lt;/strong&gt;, &lt;strong&gt;React Fiber&lt;/strong&gt;, &lt;strong&gt;Next.js routing&lt;/strong&gt;, and &lt;strong&gt;JavaScript internals&lt;/strong&gt; that power our apps every day.&lt;/p&gt;

&lt;p&gt;Instead of just memorizing answers, I decided to deeply explore every topic I encountered.&lt;br&gt;&lt;br&gt;
So I began building a small question list.&lt;/p&gt;

&lt;p&gt;Then it became 50.&lt;br&gt;&lt;br&gt;
Then 200.&lt;br&gt;&lt;br&gt;
And finally — a collection of &lt;strong&gt;over 650 questions and concepts&lt;/strong&gt; covering everything from core JavaScript to advanced React and Next.js internals.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 What’s Inside
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;💻 &lt;strong&gt;JavaScript Deep Dives&lt;/strong&gt; — event loop, call stack, microtask vs macrotask queues, shadowing, closures, promises, async/await, debouncing, throttling, memory leaks, and more.
&lt;/li&gt;
&lt;li&gt;⚛️ &lt;strong&gt;React Concepts&lt;/strong&gt; — reconciliation, Fiber, lifecycle with hooks, memoization, custom hooks, performance tuning, suspense, error boundaries, and rendering optimization.
&lt;/li&gt;
&lt;li&gt;🔗 &lt;strong&gt;Next.js&lt;/strong&gt; — SSR, SSG, ISR, RSC, parallel routing, middleware, static optimization, SEO, and API routes.
&lt;/li&gt;
&lt;li&gt;🎨 &lt;strong&gt;UI / CSS / HTML&lt;/strong&gt; — accessibility, animations, layouts, BEM, flexbox vs grid, performance, and responsive systems.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn’t just a question dump — it’s a &lt;strong&gt;structured learning roadmap&lt;/strong&gt; for frontend engineers preparing for interviews or aiming to grow into senior roles.&lt;/p&gt;




&lt;h2&gt;
  
  
  📘 The GitHub Repository
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📘 &lt;strong&gt;View the full guide here:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/maurya-sachin/Frontend-Master-Prep-Series/blob/main/README.md" rel="noopener noreferrer"&gt;Frontend Master Prep Series (650+ Questions)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s a single Markdown file you can open directly in VS Code, Obsidian, or Notion for easy reading and note-taking.&lt;br&gt;&lt;br&gt;
Each section is cleanly structured so you can use it as a reference or learning log.&lt;/p&gt;




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

&lt;p&gt;This list came together from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real interview questions I faced during recent rounds
&lt;/li&gt;
&lt;li&gt;Discussions with mentors and frontend peers
&lt;/li&gt;
&lt;li&gt;Topics I explored deeply using ChatGPT, MDN, and official documentation
&lt;/li&gt;
&lt;li&gt;Debugging challenges from my own projects like

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GENAI Document Analyzer&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kreate Energy Platform&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kreate Technologies&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Each section evolved organically as I learned — not just &lt;em&gt;what&lt;/em&gt; to answer, but &lt;em&gt;why&lt;/em&gt; things work that way.&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 What’s Next
&lt;/h2&gt;

&lt;p&gt;I’m planning to release:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧾 A &lt;strong&gt;PDF cheat sheet&lt;/strong&gt; (condensed quick notes for revision)
&lt;/li&gt;
&lt;li&gt;🧠 A &lt;strong&gt;Notion version&lt;/strong&gt; for interactive prep and progress tracking
&lt;/li&gt;
&lt;li&gt;📚 A &lt;strong&gt;topic-wise resource roadmap&lt;/strong&gt; with links to docs and tutorials
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If that sounds useful, comment below — I’ll make them public soon.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Why I Wrote This
&lt;/h2&gt;

&lt;p&gt;Because frontend interview prep shouldn’t be about memorizing buzzwords —&lt;br&gt;&lt;br&gt;
it should be about &lt;strong&gt;understanding what makes the web actually work&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This guide started as a personal learning log, but I realized it could help others too.&lt;br&gt;&lt;br&gt;
If it helps even one developer feel more confident walking into their next interview, it’s worth every late-night deep dive into React Fiber, microtask queues, and performance tuning.&lt;/p&gt;




&lt;p&gt;⭐ If you find it helpful, consider &lt;strong&gt;starring the GitHub repo&lt;/strong&gt; and sharing it with someone preparing for frontend interviews.&lt;br&gt;&lt;br&gt;
Let’s make learning a bit easier for the next person in line.  &lt;/p&gt;




&lt;h1&gt;
  
  
  frontend #react #nextjs #javascript #webdevelopment #career #interviewprep #learningjourney
&lt;/h1&gt;

</description>
      <category>resources</category>
      <category>interview</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>The Cost of Re-Renders: How to Make React Apps Actually Reactive</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Thu, 30 Oct 2025 09:44:35 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/the-cost-of-re-renders-how-to-make-react-apps-actually-reactive-3mc6</link>
      <guid>https://dev.to/maurya-sachin/the-cost-of-re-renders-how-to-make-react-apps-actually-reactive-3mc6</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;React’s biggest selling point has always been simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It’s fast because it re-renders efficiently.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But here’s the uncomfortable truth — &lt;strong&gt;React isn’t fast by default.&lt;/strong&gt;&lt;br&gt;
It’s just &lt;em&gt;forgiving&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you don’t design your state carefully, React’s virtual DOM can easily become your bottleneck.&lt;br&gt;
And the more complex your app grows, the more expensive every unnecessary re-render becomes.&lt;/p&gt;

&lt;p&gt;Let’s dissect &lt;em&gt;why&lt;/em&gt; re-renders happen, how to &lt;em&gt;avoid&lt;/em&gt; them, and what being “reactive” actually means in 2025.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;1. Every Re-Render Has a Cost&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Every React render triggers a reconciliation cycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Components re-run,&lt;/li&gt;
&lt;li&gt;Hooks re-evaluate,&lt;/li&gt;
&lt;li&gt;JSX re-diffing happens,&lt;/li&gt;
&lt;li&gt;Child components may re-render too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s all virtual, but it’s not free.&lt;br&gt;
When your app scales to hundreds of components, these micro re-renders add up — especially when tied to global or context-based state.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;2. The Silent Villain: Shared State&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Developers often push everything into Context or Redux for “simplicity.”&lt;br&gt;
The problem? Every value change triggers &lt;strong&gt;re-renders across all consumers&lt;/strong&gt;, even if most don’t use that specific part of the state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Common pattern&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ThemeContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleDarkMode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Header&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;Sidebar&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;Content&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;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if only &lt;code&gt;Header&lt;/code&gt; uses &lt;code&gt;darkMode&lt;/code&gt;, all children inside the provider re-render when it changes.&lt;br&gt;
That’s &lt;em&gt;death by a thousand re-renders&lt;/em&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;3. Memoization Isn’t a Silver Bullet&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You might say, &lt;em&gt;“I’ll just memo everything.”&lt;/em&gt;&lt;br&gt;
Sure — but memoization has its own cost.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;React.memo()&lt;/code&gt; prevents re-renders only if props are shallow-equal.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useMemo()&lt;/code&gt; and &lt;code&gt;useCallback()&lt;/code&gt; cache computations, but add complexity and memory overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re wrapping half your tree in &lt;code&gt;React.memo()&lt;/code&gt;, you’re fighting React — not optimizing it.&lt;/p&gt;

&lt;p&gt;The better solution is &lt;strong&gt;state locality&lt;/strong&gt; — keeping state as close as possible to where it’s used.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;4. Localize, Slice, and Select&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The more granular your state, the fewer components React needs to re-render.&lt;/p&gt;

&lt;p&gt;That’s why libraries like &lt;strong&gt;Zustand&lt;/strong&gt;, &lt;strong&gt;Jotai&lt;/strong&gt;, and &lt;strong&gt;Valtio&lt;/strong&gt; are so effective — they allow components to &lt;em&gt;subscribe only to the data they need.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Example (Zustand):&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;useStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;set&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;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;increment&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="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&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;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})),&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&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;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&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="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, React re-renders &lt;em&gt;only&lt;/em&gt; components using &lt;code&gt;count&lt;/code&gt;, not the entire app.&lt;br&gt;
That’s true &lt;strong&gt;reactivity&lt;/strong&gt;, not reconciliation.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;5. Fine-Grained Reactivity Is the Future&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;React’s model is coarse-grained: it re-renders entire components when state changes.&lt;br&gt;
But new paradigms (like &lt;strong&gt;Signals&lt;/strong&gt; in Solid, Qwik, and even React Canary builds) use &lt;strong&gt;fine-grained reactivity&lt;/strong&gt; — updating &lt;em&gt;only the exact DOM nodes&lt;/em&gt; that depend on changed data.&lt;/p&gt;

&lt;p&gt;This shift reduces the cost of re-renders dramatically, making UI feel instantaneous.&lt;/p&gt;

&lt;p&gt;If React 18 was about &lt;em&gt;concurrency&lt;/em&gt;, React 19+ will be about &lt;em&gt;reactivity&lt;/em&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;6. Measuring Re-Render Costs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can’t optimize what you can’t see.&lt;br&gt;
Use the React DevTools “Profiler” to measure where re-renders happen — you’ll often be surprised.&lt;/p&gt;

&lt;p&gt;Look out for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Components re-rendering without prop/state changes&lt;/li&gt;
&lt;li&gt;Context-heavy trees&lt;/li&gt;
&lt;li&gt;Missing &lt;code&gt;key&lt;/code&gt; attributes&lt;/li&gt;
&lt;li&gt;Inline object/array props&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Identifying hot spots is half the battle.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;7. The Real Goal: Flow, Not Frames&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When your React app feels slow, it’s rarely the algorithm — it’s usually the &lt;strong&gt;render flow&lt;/strong&gt;.&lt;br&gt;
True performance comes from structuring your app around &lt;em&gt;reactive data flow&lt;/em&gt;, not just faster diffing.&lt;/p&gt;

&lt;p&gt;It’s not about “preventing re-renders”; it’s about &lt;strong&gt;making every render count.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;React doesn’t slow down your app — &lt;em&gt;your architecture does.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Stop chasing &lt;code&gt;useMemo&lt;/code&gt; everywhere.&lt;br&gt;
Start designing &lt;strong&gt;state locality&lt;/strong&gt;, &lt;strong&gt;reactive data flows&lt;/strong&gt;, and &lt;strong&gt;granular subscriptions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s how modern UIs achieve “speed” — not by skipping renders, but by rendering &lt;em&gt;intelligently.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why I Wrote This&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I wrote this after noticing how often React developers (my past self included) equate “performance” with “memoization.”&lt;br&gt;
But performance doesn’t come from avoiding renders — it comes from understanding &lt;em&gt;when&lt;/em&gt; they happen and &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If this post helped you see React’s rendering model differently, I’d love to hear your take —&lt;br&gt;
How do &lt;strong&gt;you&lt;/strong&gt; handle re-renders in your projects?&lt;br&gt;
Do you rely more on memoization or on state locality patterns (like Zustand/Jotai)?&lt;/p&gt;

&lt;p&gt;Drop your thoughts below — let’s make this a conversation rather than just another React article.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Optimizing for Perceived Performance: The Psychology Behind Fast UIs</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Sat, 11 Oct 2025 18:04:16 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/optimizing-for-perceived-performance-the-psychology-behind-fast-uis-4c11</link>
      <guid>https://dev.to/maurya-sachin/optimizing-for-perceived-performance-the-psychology-behind-fast-uis-4c11</guid>
      <description>&lt;p&gt;When we talk about performance in frontend engineering, we usually mean metrics:&lt;br&gt;
&lt;strong&gt;LCP&lt;/strong&gt;, &lt;strong&gt;FID&lt;/strong&gt;, &lt;strong&gt;CLS&lt;/strong&gt;, &lt;strong&gt;INP&lt;/strong&gt;, &lt;strong&gt;TTFB&lt;/strong&gt; — numbers that quantify “speed.”&lt;/p&gt;

&lt;p&gt;But here’s the truth most developers learn the hard way:&lt;br&gt;
&lt;strong&gt;Users don’t experience speed as numbers. They experience it as &lt;em&gt;feel&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that’s what &lt;em&gt;perceived performance&lt;/em&gt; is about — how fast your app &lt;em&gt;feels&lt;/em&gt;, not just how fast it actually is.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;1. Performance ≠ Perception&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I’ve seen products that hit 95+ Lighthouse scores yet &lt;em&gt;feel sluggish&lt;/em&gt; to users.&lt;br&gt;
At the same time, I’ve built apps that score 80 but feel “instant.”&lt;/p&gt;

&lt;p&gt;Why? Because our brains don’t measure milliseconds. They respond to &lt;strong&gt;feedback, continuity, and control.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A user who sees immediate feedback (even if data isn’t ready) perceives speed.&lt;br&gt;
A user who waits with no visual cue perceives slowness — even if it’s technically faster.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;2. Skeletons, Placeholders, and the Illusion of Speed&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s take an example:&lt;br&gt;
When your app fetches data, showing nothing makes the user wait.&lt;br&gt;
Showing a skeleton makes them &lt;em&gt;feel&lt;/em&gt; progress.&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;isLoading&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;SkeletonList&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserList&lt;/span&gt; &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&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;Skeleton UIs don’t reduce load time.&lt;br&gt;
They reduce &lt;strong&gt;wait perception&lt;/strong&gt; — the most important performance metric that Lighthouse can’t measure.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;3. The Power of Optimistic Updates&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Optimistic updates are the perfect intersection of UI and psychology.&lt;/p&gt;

&lt;p&gt;You’re not waiting for the server; you’re &lt;strong&gt;trusting&lt;/strong&gt; the user’s intent.&lt;/p&gt;

&lt;p&gt;Example: liking a post, updating a task, or toggling a switch — don’t wait for confirmation. Assume success and sync 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="nf"&gt;setLiked&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="nf"&gt;updateLikeOnServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postId&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setLiked&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;p&gt;This pattern creates &lt;strong&gt;instant feedback&lt;/strong&gt;, even in high-latency environments.&lt;br&gt;
It’s a small gesture that makes your product feel confident — and that confidence transfers to the user.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;4. Transitions: The Hidden Layer of Perceived Speed&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;React’s &lt;code&gt;useTransition&lt;/code&gt; and concurrent rendering introduced a new way to &lt;strong&gt;separate urgent vs. non-urgent updates.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn’t micro-optimization — it’s &lt;em&gt;UX optimization.&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTransition&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setFilteredItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filterData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&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 UI stays responsive while heavy updates happen in the background.&lt;br&gt;
The user keeps typing, scrolling, navigating — uninterrupted.&lt;/p&gt;

&lt;p&gt;That’s perceived performance in motion.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;5. Small Delays That Feel Fast&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It’s counterintuitive, but sometimes &lt;strong&gt;adding delay makes interfaces feel smoother.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A quick example:&lt;br&gt;
If you show a spinner for only 50ms, users perceive flicker.&lt;br&gt;
If you delay it for 150–200ms, transitions feel natural.&lt;/p&gt;

&lt;p&gt;The brain interprets fluid motion as quality.&lt;br&gt;
That’s why &lt;strong&gt;Framer Motion&lt;/strong&gt; and &lt;strong&gt;GSAP&lt;/strong&gt; animations are performance tools — not just aesthetics.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;6. Perception Is a Design System Concern&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Frontend performance isn’t only a React problem.&lt;br&gt;
It’s a &lt;strong&gt;design system&lt;/strong&gt; problem.&lt;/p&gt;

&lt;p&gt;Designers define visual hierarchy; engineers define &lt;em&gt;interaction hierarchy&lt;/em&gt;.&lt;br&gt;
Knowing what needs to respond instantly (click feedback) vs. what can wait (data rendering) is what creates perceived speed.&lt;/p&gt;

&lt;p&gt;When design and engineering collaborate on feedback loops, even slow backends can &lt;em&gt;feel fast.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We obsess over performance metrics — and we should.&lt;br&gt;
But metrics can’t capture the &lt;strong&gt;emotional velocity&lt;/strong&gt; of your product.&lt;/p&gt;

&lt;p&gt;Users don’t thank you for your 100 Lighthouse score.&lt;br&gt;
They thank you for making things &lt;em&gt;feel&lt;/em&gt; instant, fluid, and alive.&lt;/p&gt;

&lt;p&gt;So next time your app “feels slow,” don’t just open DevTools.&lt;br&gt;
Ask: &lt;em&gt;Where is the user waiting without feedback?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s your real performance bottleneck.&lt;/p&gt;




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

&lt;h1&gt;
  
  
  FrontendDevelopment #ReactJS #WebPerformance #UXDesign #NextJS #JavaScript
&lt;/h1&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Lessons I Took Away from the Meta Front-End Developer Career Certificate</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Tue, 07 Oct 2025 08:40:14 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/lessons-i-took-away-from-the-meta-front-end-developer-career-certificate-2l1b</link>
      <guid>https://dev.to/maurya-sachin/lessons-i-took-away-from-the-meta-front-end-developer-career-certificate-2l1b</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
When I picked up the &lt;strong&gt;Meta Front-End Developer Career Certificate&lt;/strong&gt; on Coursera, I thought of it as just another structured path to sharpen my React and frontend skills. What I didn’t expect was how it would shift my perspective from &lt;em&gt;building pages&lt;/em&gt; to &lt;em&gt;engineering user experiences.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here’s what stood out to me.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Frontend engineering is more than visuals
&lt;/h2&gt;

&lt;p&gt;The course emphasizes HTML, CSS, and JavaScript fundamentals, but the deeper value is in accessibility and responsive design.&lt;/p&gt;

&lt;p&gt;I learned that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Semantic HTML improves accessibility for real users (and screen readers).&lt;/li&gt;
&lt;li&gt;ARIA roles aren’t optional if inclusivity is the goal.&lt;/li&gt;
&lt;li&gt;Responsive layouts are not “mobile-friendly hacks” but part of design systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This mindset helps move from “does it render?” to “does it serve everyone?”&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Performance is a feature
&lt;/h2&gt;

&lt;p&gt;One big takeaway: performance isn’t something to patch later — it’s something to design for.&lt;/p&gt;

&lt;p&gt;From my projects, I experimented with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code-splitting and dynamic imports to reduce JS bundles.&lt;/li&gt;
&lt;li&gt;Caching and ISR in Next.js for faster delivery.&lt;/li&gt;
&lt;li&gt;Image and font optimization to improve Core Web Vitals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When performance is prioritized early, users notice.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Error states matter more than happy paths
&lt;/h2&gt;

&lt;p&gt;The course introduces testing and debugging, but I pushed this further with error boundaries and resilient components.&lt;/p&gt;

&lt;p&gt;The lesson: &lt;strong&gt;a broken app erodes trust immediately.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fallback message is better than a crash.&lt;/li&gt;
&lt;li&gt;A retry button tells the user you thought ahead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good UI is defined by how it behaves under stress.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Learning compounds when you share
&lt;/h2&gt;

&lt;p&gt;I didn’t stop at completing exercises. I extended them into projects and wrote about accessibility audits, state management tradeoffs, and rendering strategies.&lt;/p&gt;

&lt;p&gt;By sharing, I not only reinforced my learning but also connected with developers who challenged me with new ideas (like diving into &lt;code&gt;useTransition&lt;/code&gt;).&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
The Meta Front-End Developer Career Certificate isn’t just about checking a box. It’s about developing the discipline to think about accessibility, performance, resilience, and communication as core parts of frontend engineering.&lt;/p&gt;

&lt;p&gt;Courses give you the scaffolding — but it’s the building, testing, and sharing that turn it into real growth.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Mastering React’s useTransition: Smooth UI Updates Without Blocking the Main Thread</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Wed, 24 Sep 2025 06:32:26 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/mastering-reacts-usetransition-smooth-ui-updates-without-blocking-the-main-thread-2ngk</link>
      <guid>https://dev.to/maurya-sachin/mastering-reacts-usetransition-smooth-ui-updates-without-blocking-the-main-thread-2ngk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction:&lt;/strong&gt;&lt;br&gt;
A few days ago, I was diving into rendering strategies in React and Next.js, discussing CSR, SSR, SSG, and ISR. One comment really caught my eye:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“useEffect ❌, useTransition ✅”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This got me curious—how can we make our React apps feel instantly responsive even under heavy state updates? That’s where &lt;code&gt;useTransition&lt;/code&gt; shines. Let’s break it down and see how to use it effectively.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Why We Need &lt;code&gt;useTransition&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
In complex React apps, updating state in big components (like large lists, dashboards, or filtered tables) can block the main thread. Typing, clicking, or scrolling feels sluggish. Traditional &lt;code&gt;useEffect&lt;/code&gt; updates can cause noticeable lag because React treats them as &lt;strong&gt;urgent&lt;/strong&gt; updates.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useTransition&lt;/code&gt; (introduced in React 18) lets us mark some updates as &lt;strong&gt;transitions&lt;/strong&gt;, which are non-urgent. React can then prioritize keeping the UI responsive while handling heavier updates in the background.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Basic Usage&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useTransition&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SearchList&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="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;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFiltered&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="nx"&gt;data&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;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTransition&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;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;startTransition&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;result&lt;/span&gt; &lt;span class="o"&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;filter&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="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="nf"&gt;setFiltered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;filtered&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="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&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;idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&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;li&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;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;isPending&lt;/code&gt;: true while the transition is in progress&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;startTransition&lt;/code&gt;: wraps state updates we want to defer&lt;/li&gt;
&lt;li&gt;Result: typing remains smooth, even for large lists&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;3. When to Use &lt;code&gt;useTransition&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typing/search in large datasets&lt;/li&gt;
&lt;li&gt;Filtering or sorting heavy lists&lt;/li&gt;
&lt;li&gt;Updating dashboards with multiple components&lt;/li&gt;
&lt;li&gt;UI interactions that must stay responsive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Best Practices&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don’t overuse: simple state toggles don’t need transitions&lt;/li&gt;
&lt;li&gt;Combine with &lt;code&gt;React.memo&lt;/code&gt; to avoid unnecessary re-renders&lt;/li&gt;
&lt;li&gt;Use with Suspense for async updates to show loaders&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;5. Real-World Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a product catalog with 1000+ items. Without &lt;code&gt;useTransition&lt;/code&gt;, typing in a search bar blocks the UI. With &lt;code&gt;useTransition&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typing stays fluid&lt;/li&gt;
&lt;li&gt;Filtered results update progressively&lt;/li&gt;
&lt;li&gt;Optional “Loading…” feedback via &lt;code&gt;isPending&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;6. Measuring Improvements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use React Profiler to see which components re-render&lt;/li&gt;
&lt;li&gt;Check Core Web Vitals for interactive performance&lt;/li&gt;
&lt;li&gt;Verify that deferred updates don’t compromise UX&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;useTransition&lt;/code&gt; is simple but powerful. It prioritizes UX over raw computation speed, making apps feel smoother and more professional. Next time your React app feels sluggish during large updates, consider marking some updates as transitions—you might be surprised by the difference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CTA:&lt;/strong&gt;&lt;br&gt;
Have you tried &lt;code&gt;useTransition&lt;/code&gt; yet? Share your experiences or tricky edge cases in the comments—I’d love to hear how you make your React apps feel lightning-fast!&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>ui</category>
    </item>
    <item>
      <title>Rendering Strategies in Next.js: CSR, SSR, SSG, ISR Explained</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Thu, 18 Sep 2025 12:41:25 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/rendering-strategies-in-nextjs-csr-ssr-ssg-isr-explained-417n</link>
      <guid>https://dev.to/maurya-sachin/rendering-strategies-in-nextjs-csr-ssr-ssg-isr-explained-417n</guid>
      <description>&lt;p&gt;Next.js gives us the flexibility to decide &lt;strong&gt;how each page should be rendered&lt;/strong&gt;.&lt;br&gt;
That flexibility is powerful — but also confusing if you don’t know the tradeoffs.&lt;/p&gt;

&lt;p&gt;In this post, let’s break down the 4 main rendering strategies in Next.js with examples and use cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Client-Side Rendering (CSR)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Page loads with minimal HTML.&lt;/li&gt;
&lt;li&gt;Data is fetched in the browser using &lt;code&gt;useEffect&lt;/code&gt; or similar hooks.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;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;Profile&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&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="p"&gt;{&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;/api/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&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="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="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;Hello &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;✅ Good for: dashboards, private user pages.&lt;br&gt;
❌ Bad for: SEO and initial load performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Server-Side Rendering (SSR)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Page HTML is generated on each request.&lt;/li&gt;
&lt;li&gt;Always up-to-date but increases server load.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;getServerSideProps&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="s2"&gt;https://api.example.com/products&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;products&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="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;products&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;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;products&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;p&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="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;p&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="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Good for: user-specific dashboards, search pages.&lt;br&gt;
❌ Bad for: pages with high traffic but static data.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Static Site Generation (SSG)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pages are built into static HTML at build time.&lt;/li&gt;
&lt;li&gt;Served instantly via CDN.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;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://api.example.com/blog&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;posts&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="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;posts&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;✅ Good for: marketing pages, blogs, docs.&lt;br&gt;
❌ Bad for: content that changes often (stock prices, news).&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Incremental Static Regeneration (ISR)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pages are pre-rendered statically, then &lt;strong&gt;revalidated on a schedule&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Combines the speed of SSG with freshness of SSR.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;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://api.example.com/products&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;products&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="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;products&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;// revalidate every 60s&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Good for: product catalogs, dashboards, news feeds.&lt;br&gt;
❌ Requires caching strategy &amp;amp; CDN setup to be effective.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing the Right Strategy
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Freshness&lt;/th&gt;
&lt;th&gt;SEO&lt;/th&gt;
&lt;th&gt;Best Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CSR&lt;/td&gt;
&lt;td&gt;Slow&lt;/td&gt;
&lt;td&gt;Fresh&lt;/td&gt;
&lt;td&gt;Poor&lt;/td&gt;
&lt;td&gt;Private dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSR&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Fresh&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;User-specific pages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSG&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Stale&lt;/td&gt;
&lt;td&gt;Great&lt;/td&gt;
&lt;td&gt;Blogs, docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ISR&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Semi-fresh&lt;/td&gt;
&lt;td&gt;Great&lt;/td&gt;
&lt;td&gt;Product listings&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;The beauty of Next.js is that you don’t need a &lt;strong&gt;one-size-fits-all&lt;/strong&gt; solution.&lt;br&gt;
You can mix rendering strategies across routes to balance speed, freshness, and scalability.&lt;/p&gt;

&lt;p&gt;👉 Pro tip: Start with &lt;strong&gt;SSG/ISR&lt;/strong&gt; for performance, and use &lt;strong&gt;SSR/CSR&lt;/strong&gt; only where absolutely necessary.&lt;/p&gt;




&lt;p&gt;💬 Which rendering strategy has worked best in your projects — and where did it fail?&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Frontend System Design: Principles for Scalable React Applications</title>
      <dc:creator>Sachin Maurya</dc:creator>
      <pubDate>Fri, 12 Sep 2025 09:37:47 +0000</pubDate>
      <link>https://dev.to/maurya-sachin/frontend-system-design-principles-for-scalable-react-applications-1i4</link>
      <guid>https://dev.to/maurya-sachin/frontend-system-design-principles-for-scalable-react-applications-1i4</guid>
      <description>&lt;p&gt;When frontend codebases grow, the challenge is rarely &lt;em&gt;just writing components&lt;/em&gt;.&lt;br&gt;
The real difficulty is keeping systems &lt;strong&gt;predictable, scalable, and maintainable&lt;/strong&gt; while still delivering performance and good UX.&lt;/p&gt;

&lt;p&gt;I want to outline some &lt;strong&gt;system design principles I’ve learned (and applied) in React/Next.js projects&lt;/strong&gt; that helped avoid tech debt and keep apps healthy at scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. State Management: Separate Concerns Early
&lt;/h2&gt;

&lt;p&gt;One of the biggest pitfalls is mixing &lt;strong&gt;server state&lt;/strong&gt; (data from APIs) with &lt;strong&gt;UI state&lt;/strong&gt; (modals, toggles, form inputs).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UI State&lt;/strong&gt; → Context or local component state is often enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server State&lt;/strong&gt; → Tools like React Query / SWR handle caching, background refetching, and stale data far better than Redux.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business Logic&lt;/strong&gt; → Redux Toolkit or Zustand shine when you need deterministic updates across the app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Rule of thumb:&lt;/strong&gt; Don’t reach for Redux by default. Reach for clarity: &lt;em&gt;Where does this state belong, and who should own it?&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Performance by Design, Not by Patching
&lt;/h2&gt;

&lt;p&gt;Performance isn’t an optimization step at the end — it’s an &lt;strong&gt;architectural decision upfront&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Examples from practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code splitting&lt;/strong&gt;: Use &lt;code&gt;React.lazy&lt;/code&gt; or Next.js dynamic imports to avoid loading entire feature modules on first paint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtualization&lt;/strong&gt;: Large lists? Always consider &lt;code&gt;react-window&lt;/code&gt; or &lt;code&gt;react-virtualized&lt;/code&gt; instead of rendering 10,000 rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching strategies&lt;/strong&gt;: Use a mix of CDN, service workers, and ISR for predictable page loads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Profiling&lt;/strong&gt;: React DevTools Profiler often reveals hidden re-render chains that add 200–300ms lag.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 If you don’t measure (Lighthouse, Web Vitals, Profiler), you’re guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Design Systems as Contracts
&lt;/h2&gt;

&lt;p&gt;A design system is more than shared buttons. It’s the &lt;strong&gt;API of your UI layer.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Design tokens&lt;/strong&gt; → centralize spacing, colors, typography.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primitives&lt;/strong&gt; → base components (&lt;code&gt;Button&lt;/code&gt;, &lt;code&gt;Input&lt;/code&gt;, &lt;code&gt;Card&lt;/code&gt;) with stable, predictable props.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt; → Storybook/Chromatic for dev visibility and design collaboration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linting/CI checks&lt;/strong&gt; → catch inline styles or rogue colors before they hit production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Treat components like APIs: predictable, versioned, and backwards-compatible.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Developer Experience = Scalability
&lt;/h2&gt;

&lt;p&gt;Bad DX kills projects faster than bad UI. If devs can’t onboard quickly, the system collapses.&lt;/p&gt;

&lt;p&gt;Practical ways to improve DX:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feature-driven folder structure (&lt;code&gt;/features/auth&lt;/code&gt;, &lt;code&gt;/features/dashboard&lt;/code&gt;) instead of “components everywhere.”&lt;/li&gt;
&lt;li&gt;Enforce standards with ESLint + Prettier + TypeScript strict mode.&lt;/li&gt;
&lt;li&gt;Pre-commit hooks (Husky + lint-staged) to prevent broken code from ever committing.&lt;/li&gt;
&lt;li&gt;Automated testing pipelines (unit + integration + E2E) baked into CI/CD.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 A good frontend system reduces cognitive load — engineers spend more time building features, less time hunting bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Frontend system design is not about adding complexity.&lt;br&gt;
It’s about applying &lt;strong&gt;structure and discipline&lt;/strong&gt; so applications scale without collapsing under their own weight.&lt;/p&gt;

&lt;p&gt;For me, the pillars are clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate state by responsibility&lt;/li&gt;
&lt;li&gt;Bake performance into architecture&lt;/li&gt;
&lt;li&gt;Treat design systems like contracts&lt;/li&gt;
&lt;li&gt;Prioritize developer experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you approach frontend this way, you stop building “pages” and start engineering &lt;strong&gt;platforms.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;💬 Question to you:&lt;br&gt;
What’s the hardest system design decision you’ve had to make on the frontend?&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>frontend</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
