<?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>Forem: Syed Muhammad Yaseen</title>
    <description>The latest articles on Forem by Syed Muhammad Yaseen (@smy).</description>
    <link>https://forem.com/smy</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%2F1651195%2F1235dfbb-3028-4d57-9549-a73427ac33ea.png</url>
      <title>Forem: Syed Muhammad Yaseen</title>
      <link>https://forem.com/smy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/smy"/>
    <language>en</language>
    <item>
      <title>Why Quick Cache Implementation Creates More Problems Than It Solves: The Hidden Tech Debt Crisis</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Wed, 30 Jul 2025 13:56:35 +0000</pubDate>
      <link>https://forem.com/smy/why-quick-cache-implementation-creates-more-problems-than-it-solves-the-hidden-tech-debt-crisis-176m</link>
      <guid>https://forem.com/smy/why-quick-cache-implementation-creates-more-problems-than-it-solves-the-hidden-tech-debt-crisis-176m</guid>
      <description>&lt;h2&gt;
  
  
  What I'm Going to Teach You
&lt;/h2&gt;

&lt;p&gt;I'm going to show you why &lt;strong&gt;rushing into cache implementation without proper planning&lt;/strong&gt; is one of the fastest ways to accumulate technical debt in your application. You'll learn the hidden complexities of cache management and how to implement caching systems that improve your codebase instead of destroying it.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The real cost of "quick and dirty" cache implementations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why cache invalidation becomes exponentially harder over time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A systematic approach to cache design that prevents tech debt&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Practical patterns for maintainable cache architectures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to refactor existing problematic cache systems&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters to You
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;That innocent "just add some caching" feature request is about to become your biggest maintenance nightmare.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're a developer who's ever been asked to "just make it faster with some caching," you're walking into a minefield. Here's what happens when you implement caching without proper architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your "simple" cache becomes a web of interdependent invalidation logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Race conditions emerge in production that never showed up in testing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data consistency bugs multiply faster than you can fix them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New features require understanding and modifying cache behaviour everywhere&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance improvements disappear as cache hit rates plummet&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your team spends more time debugging cache issues than building features&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't just a technical problem; it's a velocity killer. I've seen teams slow to a crawl because every change requires navigating a maze of cache dependencies that nobody fully understands anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Most People Fail at Caching
&lt;/h2&gt;

&lt;p&gt;Most developers fall into one of these traps when implementing caches:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Just Store It" Approach:&lt;/strong&gt; They cache data without considering invalidation strategies. Result: stale data everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Cache Everything" Approach:&lt;/strong&gt; They add caching to every function and API call. Result: a performance nightmare with no clear ownership.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Time-Based Only" Approach:&lt;/strong&gt; They rely entirely on TTL expiration. Result: users see outdated data and cache misses spike unpredictably.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Frontend Cache Chaos" Approach:&lt;/strong&gt; They implement different cache strategies across components. Result: users refresh frantically trying to see updated data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Copy-Paste Pattern" Approach:&lt;/strong&gt; They duplicate cache logic everywhere it's needed. Result: inconsistent behavior and impossible maintenance.&lt;/p&gt;

&lt;p&gt;The real issue? They don't understand that &lt;strong&gt;caching is a data consistency problem, not a performance optimization problem.&lt;/strong&gt; You're essentially creating a distributed system within your application, and distributed systems are hard.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cache Maintenance Reality Check
&lt;/h2&gt;

&lt;p&gt;Here's what implementing caching means for your codebase:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every cached piece of data becomes a state management problem.&lt;/strong&gt; You're not just storing data; you're creating multiple sources of truth that must stay synchronised.&lt;/p&gt;

&lt;p&gt;When you cache user profile data, you're signing up to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Profile updates from the user settings page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profile updates from the admin panel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profile updates from mobile apps&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profile updates from background jobs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profile updates from third-party integrations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bulk profile updates from CSV imports&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profile deletions and account deactivations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these triggers requires cache invalidation logic. Miss one, and users see stale data. Get the order wrong, and you have race conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CRUD Cache Complexity Explosion
&lt;/h2&gt;

&lt;p&gt;Let's break down what "maintaining cache" actually means:&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Operations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Where do you put new data in the cache?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you handle cache key conflicts?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What happens if the cache write fails but the database write succeeds?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you invalidate related cache entries?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Read Operations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What's your cache miss strategy?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you prevent cache stampedes?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What happens when the cache returns corrupted data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you handle partial cache hits?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Update Operations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Do you update the cache in place or invalidate?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you handle concurrent updates?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What if the cache update succeeds but the database update fails?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Which related caches need invalidation?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Delete Operations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How do you find all related cache entries to invalidate?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What happens if cache deletion fails?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do you soft delete in cache or hard delete?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you handle cascading deletes?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Frontend Cache Nightmare
&lt;/h2&gt;

&lt;p&gt;Frontend caching adds another layer of complexity because, as you mentioned, "you know how users can be":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Users open multiple tabs with different cached states&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users expect real-time updates across all their devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users refresh pages expecting to see changes immediately&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users navigate back and expect fresh data, not stale cache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users share links expecting others to see the same data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users switch between mobile and desktop, expecting consistency&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Getting fresh values every time is easy: just make the API call. With cache, you're now managing synchronisation across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Component-level state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application-level cache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Browser storage (localStorage, sessionStorage)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service worker cache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP cache headers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CDN cache layers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each layer can get out of sync, creating a debugging nightmare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache Is Not a Feature, It's Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The moment you add caching to your application, you're committing to building and maintaining a distributed data consistency system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn't hyperbole. Every cache is essentially a replica of your primary data with its consistency requirements, failure modes, and performance characteristics.&lt;/p&gt;

&lt;p&gt;Treating cache as a simple "add-on" feature is like treating database design as an afterthought. It works fine for toy applications, but it becomes a crushing technical debt burden as your system grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways: Building Maintainable Cache Systems
&lt;/h2&gt;

&lt;p&gt;To implement caching without destroying your codebase, focus on these principles:&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Design for invalidation first&lt;/strong&gt; - Before caching any data, map out every possible way that data can change and plan your invalidation strategy&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Centralise cache logic&lt;/strong&gt; - Create dedicated cache services rather than scattering cache calls throughout your codebase&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Implement cache observability&lt;/strong&gt; - You can't maintain what you can't monitor; add metrics, logging, and debugging tools from day one&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Start with course-grained caching&lt;/strong&gt; - Cache entire API responses or page-level data before optimising individual queries&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Use event-driven invalidation&lt;/strong&gt; - Build a system where data changes automatically trigger appropriate cache invalidations&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Plan for cache failures&lt;/strong&gt; - Your application must work correctly even when the cache is completely unavailable&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Document cache dependencies&lt;/strong&gt; - Maintain clear documentation of what data depends on what cache keys&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Implement gradual rollout&lt;/strong&gt; - Never deploy cache changes to all users at once; use feature flags and gradual rollouts&lt;/p&gt;

&lt;h2&gt;
  
  
  The Right Way to Approach Caching
&lt;/h2&gt;

&lt;p&gt;Instead of starting with "let's cache this API call," start with these questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is the data lifecycle?&lt;/strong&gt; How is this data created, modified, and deleted?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Who owns cache invalidation?&lt;/strong&gt; Which team/service is responsible for keeping this cache accurate?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What are the consistency requirements?&lt;/strong&gt; Is slightly stale data acceptable, or must updates be immediate?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How will you monitor cache effectiveness?&lt;/strong&gt; What metrics will tell you if caching is helping or hurting?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What's the fallback strategy?&lt;/strong&gt; What happens when the cache is down, corrupted, or returning errors?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Only after answering these questions should you start thinking about implementation details like cache keys, TTL values, and storage mechanisms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactoring Problematic Cache Systems
&lt;/h2&gt;

&lt;p&gt;If you're already living with cache technical debt, here's how to dig out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1: Audit and Document&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Map out all existing cache implementations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document cache dependencies and invalidation triggers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identify the highest-pain cache maintenance areas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 2: Consolidate&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Extract cache logic into dedicated services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Standardise on consistent cache key patterns&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement unified cache monitoring and debugging&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 3: Systematic Improvement&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Replace time-based invalidation with event-driven invalidation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add comprehensive testing for cache behaviour&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement gradual cache warming strategies&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 4: Culture Change&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make cache design reviews mandatory for new features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trainthe team on cache architecture principles&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build cache maintenance into sprint planning&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Caching done right is one of the most powerful performance optimisations available. But caching done wrong becomes a technical debt monster that consumes your team's productivity and your application's reliability.&lt;/p&gt;

&lt;p&gt;The difference isn't in the technology you choose; it's in respecting caching as a fundamental architectural decision that affects every part of your system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The next time someone asks you to "just add some caching," remember: you're not just storing data, you're designing a distributed system.&lt;/strong&gt; Treat it with the planning and respect it deserves.&lt;/p&gt;

&lt;p&gt;Your future self, your team, and your users will thank you when your application is both fast and reliable, instead of fast and buggy.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Want to learn more about building maintainable software architectures? Follow me for deep dives into solving real-world engineering challenges without creating technical debt.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>systemdesign</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Browser Tab Leader Pattern: Stop Wasting API Calls Across Browser Tabs</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Mon, 14 Jul 2025 11:09:13 +0000</pubDate>
      <link>https://forem.com/smy/browser-tab-leader-pattern-stop-wasting-api-calls-across-browser-tabs-173k</link>
      <guid>https://forem.com/smy/browser-tab-leader-pattern-stop-wasting-api-calls-across-browser-tabs-173k</guid>
      <description>&lt;h2&gt;
  
  
  What I'm Going to Teach You
&lt;/h2&gt;

&lt;p&gt;I'm going to show you how to implement a &lt;strong&gt;tab leader pattern&lt;/strong&gt; that eliminates redundant API polling across multiple browser tabs. You'll learn to build a system where only one tab handles data fetching while all others benefit from shared cache updates through localStorage and the BroadcastChannel API.&lt;/p&gt;

&lt;p&gt;By the end of this post, you'll have a complete TypeScript implementation that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Automatically elects a "leader" tab to handle API polling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shares cached data across all tabs instantly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handles edge cases like tab closure and leadership transitions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrates seamlessly with React and Redux/RTK Query&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters to You
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Every additional API call incurs a cost and degrades the user experience.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're building a dashboard, admin panel, or any multi-tab application, you're likely facing this problem right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;User opens 5 tabs of your app&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each tab polls your API every 3 minutes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your server gets hammered with 5x the necessary requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your API rate limits kick in&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users see inconsistent data across tabs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your hosting costs skyrocket&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't just a technical problem; it's a business problem. I've seen companies spending thousands extra per month on unnecessary API calls simply because they never implemented proper tab coordination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Most People Fail at This
&lt;/h2&gt;

&lt;p&gt;Most developers attempt one of these flawed approaches:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Ignore It" Approach:&lt;/strong&gt; They hope users won't open multiple tabs. Spoiler: they will.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Disable Multiple Tabs" Approach:&lt;/strong&gt; They try to prevent multiple tabs entirely. Users hate this and work around it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Complex WebSocket" Approach:&lt;/strong&gt; They over-engineer with WebSockets when simple browser APIs would suffice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ The "Shared Worker" Approach:&lt;/strong&gt; They use SharedWorker, which has poor browser support and unnecessary complexity.&lt;/p&gt;

&lt;p&gt;The real issue? They don't understand that &lt;strong&gt;tab coordination is a leadership problem, not a communication problem.&lt;/strong&gt; You need one tab to be the "leader" that does the work, while others follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tab Leader Pattern Changes Everything
&lt;/h2&gt;

&lt;p&gt;Here's the breakthrough insight: &lt;strong&gt;Treat your browser tabs like a distributed system with leader election.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of each tab acting independently, you establish a hierarchy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One leader tab&lt;/strong&gt; handles all API polling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;All follower tabs&lt;/strong&gt; listen for updates via BroadcastChannel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic failover&lt;/strong&gt; when the leader tab closes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shared cache&lt;/strong&gt; in localStorage keeps everyone in sync&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern reduces API calls by 80-90% while improving data consistency across tabs.&lt;/p&gt;

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

&lt;p&gt;By implementing this pattern, you'll achieve:&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Massive API cost reduction&lt;/strong&gt; - Only one tab polls your endpoints, regardless of how many tabs are open&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Improved performance&lt;/strong&gt; - No more duplicate network requests slowing down your app&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Better user experience&lt;/strong&gt; - Consistent data across all tabs with instant updates&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Automatic failover&lt;/strong&gt; - When the leader tab closes, another tab seamlessly takes over&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Zero configuration&lt;/strong&gt; - The system self-organises without any user intervention&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Framework agnostic&lt;/strong&gt; - Works with React, Vue, Angular, or vanilla JavaScript&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Production-ready&lt;/strong&gt; - Handles edge cases like rapid tab switching and network failures&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Type-safe implementation&lt;/strong&gt; - Full TypeScript support with proper error handling&lt;/p&gt;

&lt;h2&gt;
  
  
  The Complete Implementation
&lt;/h2&gt;

&lt;p&gt;Let's build this step by step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: The Core Leadership Manager
&lt;/h3&gt;

&lt;p&gt;First, we need a system to elect and maintain a leader tab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pollingLeaderManager.ts&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastPollTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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;CHANNEL_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;polling-leader&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;LEADER_TTL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isLeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;tabId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BroadcastChannel&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pingInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NodeJS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Timeout&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;leaderTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NodeJS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Timeout&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;initialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastLeaderPollTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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;notifyListeners&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastLeaderPollTime&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;subscribeToLeadership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastLeaderPollTime&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;listeners&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listeners&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;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;listener&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initPollingLeader&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="nx"&gt;initialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;initialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;channel&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;BroadcastChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CHANNEL_NAME&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;sendPing&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tabId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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;becomeLeader&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;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;isLeader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;isLeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;lastLeaderPollTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;notifyListeners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;sendPing&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;loseLeadership&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;isLeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;notifyListeners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleMessage&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="nx"&gt;MessageEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &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="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="nx"&gt;tabId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;tabId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;loseLeadership&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;resetLeaderTimeout&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetLeaderTimeout&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leaderTimeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leaderTimeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;leaderTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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;becomeLeader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;LEADER_TTL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;resetLeaderTimeout&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;pingInterval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;sendPing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;LEADER_TTL&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beforeunload&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;channel&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pingInterval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pingInterval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leaderTimeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leaderTimeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each tab gets a unique ID and listens to a BroadcastChannel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leader tabs send "ping" messages every 4 seconds&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a tab doesn't hear pings for 5.5 seconds, it assumes leadership&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean shutdown handling prevents zombie leaders&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: The Polling Hook
&lt;/h3&gt;

&lt;p&gt;Next, we create a React hook that handles the actual polling logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// useLeaderPollingEffect.ts&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;useRef&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;const&lt;/span&gt; &lt;span class="nx"&gt;POLLING_INTERVAL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;180000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 3 minutes&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POLLING_DEBOUNCE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&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;LAST_POLL_TIME_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;last_poll_time&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;getLastPollTimeFromStorage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LAST_POLL_TIME_KEY&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;stored&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stored&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setLastPollTimeInStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LAST_POLL_TIME_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useLeaderPollingEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;lastLeaderPollTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;pollingFns&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="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)[]&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervalRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NodeJS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Timeout&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="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="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;isLeader&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="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&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;lastStoredPollTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getLastPollTimeFromStorage&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;currentTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeSinceLastPoll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastStoredPollTime&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;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&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="nx"&gt;POLLING_INTERVAL&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;timeSinceLastPoll&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;runPolling&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;pollingFns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
      &lt;span class="nf"&gt;setLastPollTimeInStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;runPolling&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;runPolling&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;POLLING_INTERVAL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;timeSinceLastPoll&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;POLLING_INTERVAL&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;POLLING_DEBOUNCE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;delay&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="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastLeaderPollTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pollingFns&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Only polls when the tab is the leader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calculates smart delays based on the last poll time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prevents rapid polling during leadership transitions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Persists timing across tab changes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: The Main Hook
&lt;/h3&gt;

&lt;p&gt;Create a simple interface for components to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// usePollingLeader.ts&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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initPollingLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subscribeToLeadership&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;./pollingLeaderManager&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;usePollingLeader&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;isLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLeader&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;false&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;lastPollTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLastPollTime&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="mi"&gt;0&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;initPollingLeader&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;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;subscribeToLeadership&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastPollTime&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;setIsLeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setLastPollTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastPollTime&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;unsubscribe&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="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastPollTime&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Real-World Usage
&lt;/h3&gt;

&lt;p&gt;Here's how to use it in your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AuthorizedLayout.tsx&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;useMemo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;usePollingLeader&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;./usePollingLeader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLeaderPollingEffect&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;./useLeaderPollingEffect&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;AuthorizedLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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;isLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastPollTime&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePollingLeader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Define your API calls&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pollingFns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;triggerGetAllAttributes&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;triggerGetAllCustomEventsWithProperties&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;triggerGetAllAttributesWithProperties&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;triggerGetAllSegments&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;triggerGetChannelConfig&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="cm"&gt;/* your dependencies */&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// Only the leader tab will execute these&lt;/span&gt;
  &lt;span class="nf"&gt;useLeaderPollingEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastPollTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pollingFns&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Error Handling
&lt;/h3&gt;

&lt;p&gt;Add retry logic and error boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runPolling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="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="nx"&gt;pollingFns&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;fn&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="nf"&gt;setLastPollTimeInStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Polling failed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Implement exponential backoff&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Performance Optimization
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;useMemo&lt;/code&gt; for polling functions to prevent unnecessary re-renders&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement request deduplication at the API layer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider using &lt;code&gt;requestIdleCallback&lt;/code&gt; For non-critical updates&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;Mock BroadcastChannel in your tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test-utils.ts&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MockBroadcastChannel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addEventListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;postMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BroadcastChannel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MockBroadcastChannel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Browser Support and Fallbacks
&lt;/h2&gt;

&lt;p&gt;BroadcastChannel has excellent modern browser support but consider fallbacks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasSupport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;BroadcastChannel&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="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;hasSupport&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Fallback to polling in each tab&lt;/span&gt;
  &lt;span class="c1"&gt;// Or use a different communication method&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The tab leader pattern is a game-changer for multi-tab applications. It's the difference between a system that scales elegantly and one that crumbles under its API requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The best part?&lt;/strong&gt; Your users will never notice the complexity; they'll just experience faster, more consistent data across all their tabs while your API costs plummet.&lt;/p&gt;

&lt;p&gt;Start with the core implementation above, then customise it for your specific use case. Your future self (and your hosting bill) will thank you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Want to see more advanced patterns like this? Follow me for more deep dives into solving real-world frontend challenges.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Shadow DOM: The Ultimate Solution for Embedding Third-Party HTML Without CSS Conflicts</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Mon, 14 Jul 2025 11:05:57 +0000</pubDate>
      <link>https://forem.com/smy/shadow-dom-the-ultimate-solution-for-embedding-third-party-html-without-css-conflicts-1g2g</link>
      <guid>https://forem.com/smy/shadow-dom-the-ultimate-solution-for-embedding-third-party-html-without-css-conflicts-1g2g</guid>
      <description>&lt;h2&gt;
  
  
  What You'll Learn in This Guide
&lt;/h2&gt;

&lt;p&gt;By the end of this article, you'll master:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What Shadow DOM is and why it's a game-changer for web development&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to implement Shadow DOM to isolate third-party HTML content&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-world techniques for embedding HTML templates without CSS conflicts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advanced patterns for mobile simulation and responsive previews&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Best practices for maintaining control over embedded content&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters to You (And Your Sanity)
&lt;/h2&gt;

&lt;p&gt;Picture this: You've a beautiful email template builder. Users create stunning templates, and now you need to display these templates on your main platform for preview. Simple, right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The moment you inject that HTML into your DOM, chaos ensues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your carefully crafted platform styles get overridden&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The template's CSS bleeds into your UI components&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Buttons break, layouts shift, and your design system crumbles&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users report bugs that seem impossible to reproduce&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sound familiar? You're not alone. This is the #1 pain point for developers building platforms that handle user-generated or third-party HTML content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Most Developers Fail at HTML Isolation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The iframe trap&lt;/strong&gt;: Most developers reach for iframes as their first solution. Sure, iframes provide perfect isolation, but they come with deal-breaking limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No programmatic control over the content&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complex communication between parent and child&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mobile responsiveness nightmares&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SEO and accessibility issues&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The CSS namespace illusion&lt;/strong&gt;: Others try to solve this with CSS namespacing, BEM methodologies, or CSS-in-JS solutions. These approaches are like putting a band-aid on a broken dam; they might work for simple cases, but they inevitably fail when dealing with complex, dynamic content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The sanitisation maze&lt;/strong&gt;: Some developers go down the rabbit hole of HTML sanitisation and CSS parsing. While important for security, this approach is fragile, performance-heavy, and often breaks legitimate styling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shadow DOM Is the Future of Content Isolation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Here's the truth&lt;/strong&gt;: Shadow DOM is the web standard specifically designed to solve this exact problem. It's not just a hack or workaround; it's a fundamental browser feature that creates true style and DOM isolation.&lt;/p&gt;

&lt;p&gt;Unlike other solutions, Shadow DOM gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;True encapsulation&lt;/strong&gt;: Styles cannot leak in or out&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Full programmatic control&lt;/strong&gt;: Access and manipulate content as needed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Native browser support&lt;/strong&gt;: No external dependencies or performance overhead&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexible architecture&lt;/strong&gt;: Works with any framework or vanilla JavaScript&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;• &lt;strong&gt;Shadow DOM creates isolated DOM trees&lt;/strong&gt; that prevent CSS conflicts between your platform and embedded content&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Unlike iframes, Shadow DOM allows full programmatic control&lt;/strong&gt; while maintaining perfect style isolation&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Mobile simulation becomes trivial&lt;/strong&gt; when you control the viewport dimensions within the shadow root&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Performance is superior&lt;/strong&gt; to iframe solutions since everything runs in the same document context&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Browser support is excellent&lt;/strong&gt;, and Shadow DOM is supported in all modern browsers&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Security boundaries are maintained&lt;/strong&gt; while allowing controlled interaction between the host and embedded content&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Use Case: Email Template Preview Platform
&lt;/h2&gt;

&lt;p&gt;Let me walk you through a real scenario I encountered while building an email template builder platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge
&lt;/h3&gt;

&lt;p&gt;We have built an email template builder where users can create complex HTML templates with custom CSS. The challenge was displaying these templates on our main platform for preview without:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Breaking our existing UI components&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Having template styles leak into our design system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Losing the ability to programmatically control the preview (ruling out iframes)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating mobile-responsive preview modes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Shadow DOM Solution
&lt;/h3&gt;

&lt;p&gt;Here's an example of implementing a robust solution using Shadow DOM:&lt;br&gt;&lt;br&gt;
Sure, it can be refactored even further; this is just to give an idea.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRef&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;useCallback&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UseShadowDOMPreviewReturn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;containerRef&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="nx"&gt;RefObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;showPreview&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="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;hidePreview&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="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useShadowDOMPreview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;isMobile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UseShadowDOMPreviewReturn&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;containerRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ShadowRoot&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Create isolated Shadow DOM&lt;/span&gt;
      &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="c1"&gt;// Define viewport dimensions&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mobileWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;375&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;mobileHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;667&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="c1"&gt;// Create isolated styles&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styleElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;styleElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
        :host {
          all: initial;
          display: none;
          position: fixed;
          top: 0;
          left: 0;
          z-index: 9999;
          background: white;
          &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`
            width: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mobileWidth&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px;
            height: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mobileHeight&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            border: 2px solid #ccc;
            border-radius: 20px;
            overflow: hidden;
            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
          `&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
            width: 100%;
            height: 100%;
          `&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
        }

        &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`
          /* Mobile simulation styles */
          * {
            -webkit-text-size-adjust: 100%;
            -webkit-tap-highlight-color: transparent;
          }

          html, body {
            width: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mobileWidth&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px !important;
            height: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mobileHeight&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px !important;
            margin: 0 !important;
            padding: 0 !important;
            overflow-x: hidden !important;
            font-size: 16px !important;
          }

          button, a, input {
            min-height: 44px !important;
            min-width: 44px !important;
          }
        `&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="s2"&gt;
      `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isMobile&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Clear previous content while preserving styles&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styleElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// Process HTML for mobile if needed&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;processedHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;processedHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
          &amp;lt;div class="mobile-container" style="
            width: 100%;
            height: 100%;
            overflow: auto;
            -webkit-overflow-scrolling: touch;
          "&amp;gt;
            &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
          &amp;lt;/div&amp;gt;
        `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// Inject isolated content&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;contentDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;processedHtml&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentDiv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Add mobile environment simulation&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;isMobile&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;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
          // Override window dimensions for mobile simulation
          Object.defineProperty(window, 'innerWidth', { value: 375 });
          Object.defineProperty(window, 'innerHeight', { value: 667 });
          Object.defineProperty(navigator, 'userAgent', { 
            value: 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15'
          });
        `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isMobile&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;showPreview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;block&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="p"&gt;[]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hidePreview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&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="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showPreview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hidePreview&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementation in React Component
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EmailTemplatePreview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isMobile&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showPreview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hidePreview&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useShadowDOMPreview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;isMobile&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Isolated preview container */&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;div&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;containerRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email-preview"&lt;/span&gt;
        &lt;span class="na"&gt;style&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="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Platform UI remains unaffected */&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"preview-controls"&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;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showPreview&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Preview &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mobile&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;Desktop&lt;/span&gt;&lt;span class="dl"&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="nc"&gt;Button&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;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hidePreview&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"outline"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Close Preview
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&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;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Results: Why This Approach Wins
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Perfect Style Isolation
&lt;/h3&gt;

&lt;p&gt;No more CSS conflicts. Our platform styles remained pristine while email templates displayed exactly as intended. The Shadow DOM boundary acted as an impenetrable wall between the two style contexts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mobile Simulation Made Simple
&lt;/h3&gt;

&lt;p&gt;By controlling the viewport dimensions within the Shadow DOM, we created pixel-perfect mobile previews without the complexity of device detection or responsive breakpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintained Control
&lt;/h3&gt;

&lt;p&gt;Unlike iframe solutions, we could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Programmatically show/hide previews&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access and modify content when needed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handle user interactions seamlessly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement custom loading states and error handling&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Superior Performance
&lt;/h3&gt;

&lt;p&gt;Everything ran in the same document context, eliminating the overhead of iframe communication and cross-frame data transfer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Patterns and Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Device-Specific Simulation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DEVICE_PRESETS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iphone-se&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;375&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;667&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iphone-12&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;390&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;844&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;android&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;640&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Use specific device configurations&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DEVICE_PRESETS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iphone-12&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;containerRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showPreview&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useShadowDOMPreview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;device&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Event Handling Across Shadow Boundaries
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle clicks within shadow DOM&lt;/span&gt;
    &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&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;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;target&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="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close-button&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;hidePreview&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hidePreview&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Dynamic Content Updates
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatePreviewContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;newContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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;contentContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shadowRootRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentContainer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;contentContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newContent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;p&gt;While Shadow DOM provides style isolation, remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sanitize HTML content&lt;/strong&gt; before injection to prevent XSS attacks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use CSP headers&lt;/strong&gt; to restrict script execution within shadow roots&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validate user-generated content&lt;/strong&gt; even within isolated contexts&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;DOMPurify&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;dompurify&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;sanitizedHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userHtml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ADD_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;custom-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;ADD_ATTR&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;custom-attr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Browser Compatibility and Fallbacks
&lt;/h2&gt;

&lt;p&gt;Shadow DOM enjoys excellent modern browser support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Chrome 53+&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Firefox 63+&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Safari 10+&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edge 79+&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For older browsers, consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasShadowDOMSupport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;attachShadow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&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;hasShadowDOMSupport&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Fallback to iframe or alternative solution&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;IframePreview&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion: Shadow DOM is Your Secret Weapon
&lt;/h2&gt;

&lt;p&gt;Shadow DOM isn't just another web API; it's a paradigm shift in how we think about content isolation and component architecture. For developers building platforms that handle third-party HTML, email builders, widget systems, or any application requiring style isolation, Shadow DOM is not optional; it's essential.&lt;/p&gt;

&lt;p&gt;The next time you face the challenge of embedding HTML content without CSS conflicts, remember: you don't need complex workarounds or fragile hacks. You need Shadow DOM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ready to implement Shadow DOM in your project?&lt;/strong&gt; Begin with the patterns presented in this article and gradually expand to more complex use cases. Your future self (and your users) will thank you for choosing the right tool for the job.&lt;/p&gt;




&lt;p&gt;That’s it, folks! Hope it was a good read 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Avoid Chrome Flagging Your Web Push Notifications (And Why Most People Get It Wrong)</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Mon, 14 Jul 2025 11:04:03 +0000</pubDate>
      <link>https://forem.com/smy/how-to-avoid-chrome-flagging-your-web-push-notifications-and-why-most-people-get-it-wrong-18bk</link>
      <guid>https://forem.com/smy/how-to-avoid-chrome-flagging-your-web-push-notifications-and-why-most-people-get-it-wrong-18bk</guid>
      <description>&lt;p&gt;&lt;strong&gt;What I will teach you:&lt;/strong&gt; How to ensure your web push notifications don’t get flagged or blocked by Chrome’s new spam detection system, using real-world testing, simple language shifts, and smart campaign practices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ls703m3ppm9w2q04kpx.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ls703m3ppm9w2q04kpx.webp" alt="Chrome possible spam warning for push notification on Android" width="540" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters: Chrome’s New Spam Detection System
&lt;/h2&gt;

&lt;p&gt;In May 2025, Google Chrome introduced an on-device machine learning system that filters out push notifications it sees as misleading or spammy. If your message triggers this filter, users might never even see it. That means lower engagement, wasted campaigns, and lost sales, even if your notification is legit.&lt;/p&gt;

&lt;p&gt;Chrome’s update includes a machine learning model that runs directly on Android devices, powered by &lt;strong&gt;Gemini&lt;/strong&gt; and trained on both real and synthetic data. This enables Chrome to detect suspicious push content locally, making it faster and more private, as it doesn’t rely on sending user data to external servers.&lt;/p&gt;

&lt;p&gt;When a notification is flagged, Chrome displays a warning showing the site name and gives users options to unsubscribe or view the message. The model evaluates titles, bodies, and even action button text.&lt;/p&gt;

&lt;p&gt;Read the official blog post here: &lt;a href="https://blog.chromium.org/2025/05/fighting-unwanted-notifications-with.html" rel="noopener noreferrer"&gt;Chrome Fighting Unwanted Notifications&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, Chrome’s &lt;strong&gt;Safety Check&lt;/strong&gt; feature now runs automatically in the background, revoking permissions from sites users no longer visit or that send misleading messages. Users can also unsubscribe from push messages directly from the notification panel, contributing to a 30% reduction in total notifications on supported devices.&lt;/p&gt;

&lt;p&gt;This is especially critical if you rely on push for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Flash sales&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delivery alerts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limited-time campaigns&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-engagement with inactive users&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Most People Fail at Push Notifications
&lt;/h2&gt;

&lt;p&gt;Most marketers and developers test once, see it works, and assume all is good.&lt;/p&gt;

&lt;p&gt;But Chrome’s system learns. That first message might go through, but the same message tomorrow? Blocked.&lt;/p&gt;

&lt;p&gt;Even worse, they use language that &lt;em&gt;sounds&lt;/em&gt; great but gets flagged — words like "FREE," "WIN," or vague titles like "Act Now" or "Delivery Alert."&lt;/p&gt;




&lt;h2&gt;
  
  
  My Real-World Testing Experience: What I Learned
&lt;/h2&gt;

&lt;p&gt;I was helping run a push campaign for a beauty brand, and this is what I learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Sent: "KLEAN BEAUTY PRODUCTS ARRIVED - FREE Delivery!" — Delivered the first time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sent it again a few hours later — Blocked&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removed the word &lt;strong&gt;FREE&lt;/strong&gt; — Worked perfectly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added back &lt;strong&gt;FREE&lt;/strong&gt; — Blocked again&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tried title: "Klean Beauty to Cart Delivery!" — Still blocked (too vague)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added a red siren emoji 🚨 to the title — Also blocked&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s when I realised: this isn't just about &lt;em&gt;what&lt;/em&gt; you say, it’s &lt;em&gt;how&lt;/em&gt; you say it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Topical Takeaway: Chrome Is Actively Filtering Your Push Content
&lt;/h2&gt;

&lt;p&gt;Chrome now actively filters your push content based on wording, repetition, and user behaviour. Ignore this, and your campaign performance will tank.&lt;/p&gt;




&lt;h2&gt;
  
  
  7 Rules to Avoid Getting Flagged by Chrome
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid buzzwords:&lt;/strong&gt; FREE, WIN, URGENT, or ACT NOW are red flags.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don’t use vague phrasing:&lt;/strong&gt; Titles like "to cart delivery" or "click here" confuse users and get flagged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don’t imitate system messages:&lt;/strong&gt; Chrome watches for notifications that look like OS/system alerts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test more than once:&lt;/strong&gt; A message working once doesn’t mean it’ll work twice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Send to your device first:&lt;/strong&gt; Repeatedly. If it disappears or shows a warning, change it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be transparent with opt-ins:&lt;/strong&gt; Never trick users into allowing notifications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep it clear and concise:&lt;/strong&gt; "Your Klean Beauty order qualifies for delivery" works better than "Klean Beauty to Cart Delivery!"&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Bottom Line: Adapt or Get Blocked
&lt;/h2&gt;

&lt;p&gt;If you're sending push notifications in 2025 and not adapting to Chrome's new system, you're flying blind. Learn the rules, test smart, and keep your language honest and clear.&lt;/p&gt;

&lt;p&gt;This small shift can mean the difference between a successful campaign and one that never even lands.&lt;/p&gt;




&lt;p&gt;That’s it, folks! Hope it was a good read 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>security</category>
    </item>
    <item>
      <title>How I Started My Software Engineering Career (and Why)</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Mon, 14 Jul 2025 10:55:11 +0000</pubDate>
      <link>https://forem.com/smy/how-i-started-my-software-engineering-career-and-why-25ad</link>
      <guid>https://forem.com/smy/how-i-started-my-software-engineering-career-and-why-25ad</guid>
      <description>&lt;p&gt;Some stories begin with a dramatic moment. Mine began with a PlayStation 1 and a dusty DOS computer in the early 2000s.&lt;/p&gt;

&lt;p&gt;I was just four years old, more fascinated with &lt;em&gt;Spyro&lt;/em&gt; and &lt;em&gt;Dragon Ball&lt;/em&gt; than anything else. But even then, I was drawn to what made things &lt;em&gt;work&lt;/em&gt;. The PS1 was for play, but the DOS computer? That was a mystery box I wanted to explore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Childhood Curiosity: From Games to Geek Mode
&lt;/h2&gt;

&lt;p&gt;When I was five or six years old, my father brought home a &lt;strong&gt;Pentium 3 PC&lt;/strong&gt;. It wasn’t cutting-edge by any means, but to me, it felt like the future had finally arrived. I’d spend hours playing &lt;strong&gt;Red Alert 2&lt;/strong&gt;, using &lt;strong&gt;Sega SNES emulators&lt;/strong&gt;, and enjoying browser games on &lt;strong&gt;Miniclip&lt;/strong&gt; and &lt;strong&gt;Y8&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Later, we got a &lt;strong&gt;PlayStation 2&lt;/strong&gt;, which we had &lt;em&gt;modded&lt;/em&gt; to run pirated games. I vividly remember buying blank &lt;strong&gt;DVD-RWs&lt;/strong&gt;, downloading PS2 games via &lt;strong&gt;torrents&lt;/strong&gt;, burning them, and getting to play an endless variety of titles. It was thrilling, but also a hands-on tech lesson in file formats, disc burning, and troubleshooting.&lt;/p&gt;

&lt;p&gt;However, unlike most kids, I wasn’t just focused on gaming. I was equally curious about what made everything tick. I learned to &lt;strong&gt;install and customize Windows&lt;/strong&gt;, set up software, and fix common system problems. My fun and my learning were deeply intertwined, even if I didn’t realize it then.&lt;/p&gt;

&lt;p&gt;By the age of 10, we had a &lt;strong&gt;Pentium 4&lt;/strong&gt;, and my curiosity had only grown deeper. I was in Class 4 when I made a decision that would stick with me for life:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I want to work with computers, either as a Computer Scientist or Computer Engineer.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No backup plans. No wavering.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Encounters With Code (And Failing Fast)
&lt;/h2&gt;

&lt;p&gt;In 2013, I decided to learn &lt;strong&gt;C++&lt;/strong&gt; for no particular reason other than the name sounded... powerful. It took just 2–3 days to realize I didn’t understand a thing. So I gave up.&lt;/p&gt;

&lt;p&gt;But failure didn’t stop me. I shifted to game development using &lt;strong&gt;Construct 2&lt;/strong&gt;, a drag-and-drop engine. That too didn’t last long, but each failed attempt planted a seed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovering the Web: MERN, CS50 &amp;amp; the First Sparks
&lt;/h2&gt;

&lt;p&gt;In 2017, a &lt;a href="https://hackernoon.com/full-time-developer-in-just-a-few-months-zero-to-mastery-case-studies-b3c3ca3bcb24" rel="noopener noreferrer"&gt;&lt;strong&gt;HackerNoon&lt;/strong&gt; blog by &lt;em&gt;Andrei Neagoie&lt;/em&gt;&lt;/a&gt; introduced me to the &lt;strong&gt;MERN stack&lt;/strong&gt;. The blog linked to a &lt;a href="https://www.udemy.com/course/the-complete-web-developer-zero-to-mastery/?couponCode=KEEPLEARNING18&amp;amp;ref=hackernoon.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Udemy course&lt;/strong&gt;&lt;/a&gt;, possibly one of the best I’ve ever taken. I dived in and absorbed everything from the fundamentals of the web to Git, Heroku, APIs, and the MERN stack itself.&lt;/p&gt;

&lt;p&gt;Unfortunately, my academic life got in the way. Grades 11 and 12 were packed with exam pressure, so I had to hit pause.&lt;/p&gt;

&lt;p&gt;But the fire reignited in 2018 when I found &lt;strong&gt;Harvard’s CS50&lt;/strong&gt; on YouTube. Every lecture was over an hour long, but I was hooked. CS50 changed how I thought about programming and learning.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Honestly, I think every CS student should watch it before starting university. It gives you a glimpse of what's coming.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Rust, Embedded Systems, and PIAIC
&lt;/h2&gt;

&lt;p&gt;In 2019, I joined &lt;strong&gt;PIAIC’s IoT program&lt;/strong&gt;. They taught IoT using &lt;strong&gt;Rust&lt;/strong&gt;, and later &lt;strong&gt;Embedded Rust&lt;/strong&gt;. It was fascinating, but tough. I had no background in hardware or registers, and my university had just started. After completing three quarters, I had to step away due to the difficulty and lack of time.&lt;/p&gt;

&lt;p&gt;But I did what I always do, &lt;strong&gt;kept moving forward&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entering University (and Not Waiting for Graduation)
&lt;/h2&gt;

&lt;p&gt;When I enrolled in a &lt;strong&gt;Computer Science&lt;/strong&gt; degree in 2019, I had one goal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Don’t wait until graduation to start your career.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I opened a &lt;strong&gt;LinkedIn&lt;/strong&gt; account, followed industry leaders, and started posting my learning journey.&lt;/p&gt;

&lt;p&gt;In 2020, during my second semester, we had a course on Java and OOP. After just a few classes, I realized the instructor would only cover the basics, slowly. So, I decided to teach myself &lt;strong&gt;Java&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I found a roadmap and what I believe is the &lt;a href="https://www.udemy.com/course/java-the-complete-java-developer-course/" rel="noopener noreferrer"&gt;best Java course online&lt;/a&gt;. I covered more in two weeks than the course would in four months. I dove deep, &lt;strong&gt;Java Core&lt;/strong&gt;, &lt;strong&gt;JavaFX GUIs&lt;/strong&gt;, &lt;strong&gt;APIs&lt;/strong&gt;, and eventually &lt;strong&gt;Spring Boot&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Java is where my actual programming skills began to develop, where I truly understood the concepts, and learned them deeply. Practising all the time, building and sharing stuff over LinkedIn.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Steps Into Freelancing
&lt;/h2&gt;

&lt;p&gt;At the start of 2021, I jumped into freelancing via &lt;strong&gt;Upwork&lt;/strong&gt;. It took two months of persistence to land my first project, changing a YouTube loader on a website. After that came a &lt;strong&gt;Selenium script&lt;/strong&gt; (which I learned in four hours using Google), &lt;strong&gt;PDF generator with Java&lt;/strong&gt;, &lt;strong&gt;Minecraft server setups on Linux&lt;/strong&gt;, and completely random gigs that taught me a lot.&lt;/p&gt;

&lt;p&gt;Around the same time, I joined platforms like &lt;strong&gt;Interns Pakistan&lt;/strong&gt; and &lt;strong&gt;The Sparks Foundation&lt;/strong&gt;, where I earned certificates for completing courses and projects. I posted everything I could on LinkedIn.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Something is better than nothing.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Applied to many places for Internship
&lt;/h2&gt;

&lt;p&gt;I applied to many places for an internship, and did some interviews, but eventually failed to get into all of them. Well, of course, I was sad, but didn’t stop there.&lt;/p&gt;

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

&lt;p&gt;Here’s my first-ever Resume, made with Canva lol.&lt;/p&gt;

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

&lt;p&gt;Applied hundreds of times to many places, making hundreds of changes to my resume:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Breakthrough: Nisum Internship
&lt;/h2&gt;

&lt;p&gt;In May 2021, I saw a &lt;strong&gt;LinkedIn&lt;/strong&gt; post from &lt;strong&gt;Nisum&lt;/strong&gt;, a software services company, hiring interns. I&lt;br&gt;&lt;br&gt;
reached out to their employees, networked, and finally, someone forwarded my resume.&lt;/p&gt;

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

&lt;p&gt;Resume:&lt;/p&gt;

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

&lt;p&gt;Cover Letter:&lt;/p&gt;

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

&lt;p&gt;There were three rounds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Written Test&lt;/strong&gt; – IQ, math, and algorithms&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;First Interview&lt;/strong&gt; – 35 minutes of Core Java grilling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Final Interview&lt;/strong&gt; – More fundamentals&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I was confident, and it paid off. I was in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrapping in the Real World
&lt;/h2&gt;

&lt;p&gt;On the first day, I found myself among a group of 12 interns: some in Java, some in DevOps, some in QA. I was placed in &lt;strong&gt;MERN&lt;/strong&gt;, which surprised me, but I embraced it.&lt;/p&gt;

&lt;p&gt;My mentor, a senior engineer, didn't toss me into endless tutorials. Instead, he introduced me to HackerRank and gave me a week to sharpen my logic using JavaScript. After that, I spent about two weeks learning raw HTML and CSS.&lt;/p&gt;

&lt;p&gt;Once I grasped the basics, I started building projects with raw HTML, CSS, and JavaScript. This experience helped me understand core concepts, such as promises beginning with callback hell, moving on to long chains of then clauses, and eventually mastering async/await, along with many other JavaScript fundamentals.&lt;/p&gt;

&lt;p&gt;I was tasked with creating a Trello-like project using only raw HTML, CSS, and JavaScript. This experience made me appreciate the challenges that modern frameworks and libraries aim to solve. Eventually, I had to make a decision: should I choose React, Vue, or Angular?&lt;/p&gt;

&lt;p&gt;I chose &lt;strong&gt;React&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Eventually, all MERN and QA interns were grouped into a project: a &lt;strong&gt;food ordering app&lt;/strong&gt; to automate the office lunch system. We had three mentors, two QA teammates, and two months to deliver.&lt;/p&gt;

&lt;p&gt;We built a full-stack &lt;strong&gt;MERN&lt;/strong&gt; app, complete with custom order management and &lt;strong&gt;PWA mobile support&lt;/strong&gt;. I often worked 12-hour days, it didn’t feel like work. I was &lt;em&gt;building&lt;/em&gt; something real.&lt;/p&gt;

&lt;p&gt;At the end of three months, &lt;strong&gt;I was offered a permanent position&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;I had just started my 5th semester at that time. Luckily, my university was just a 10-minute ride from the office, making the commute easy.  &lt;/p&gt;

&lt;p&gt;The job required a commitment of 45 hours per week, and I covered the remaining hours on days when I didn’t have classes.&lt;/p&gt;

&lt;p&gt;After my classes, I would come in and stay until around 11 - 12 P.M.&lt;/p&gt;

&lt;p&gt;I am truly grateful for my supportive colleagues, as their cooperation helped me balance my studies while working full-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflection
&lt;/h2&gt;

&lt;p&gt;Fast forward 4 years, my resume:&lt;/p&gt;

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

&lt;p&gt;My software engineering career didn’t happen overnight.&lt;/p&gt;

&lt;p&gt;It was a long chain of failed experiments, small wins, online communities, mentors, and &lt;em&gt;a lot of curiosity&lt;/em&gt;. From a kid gaming on Red Alert 2 to solving real-world problems with code, this is the journey I’m proud of.&lt;/p&gt;

&lt;p&gt;And it's just the beginning.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>java</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How I Made My Next.js Blog Serve Markdown Files for Agent Experience SEO (AX-SEO)</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Mon, 14 Jul 2025 10:45:47 +0000</pubDate>
      <link>https://forem.com/smy/how-i-made-my-nextjs-blog-serve-markdown-files-for-agent-experience-seo-ax-seo-k62</link>
      <guid>https://forem.com/smy/how-i-made-my-nextjs-blog-serve-markdown-files-for-agent-experience-seo-ax-seo-k62</guid>
      <description>&lt;p&gt;I’ll show you how to serve &lt;strong&gt;raw Markdown files&lt;/strong&gt; in a &lt;strong&gt;Next.js blog&lt;/strong&gt; using &lt;strong&gt;middleware and API routes&lt;/strong&gt;, enabling &lt;strong&gt;Agent Experience SEO (AX-SEO)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;AX-SEO focuses on optimizing content for &lt;strong&gt;AI agents, LLM-powered search engines, and automated crawlers&lt;/strong&gt; that now play a major role in content discovery.&lt;/p&gt;

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

&lt;p&gt;✅ Implement &lt;strong&gt;Next.js middleware&lt;/strong&gt; for &lt;code&gt;.md&lt;/code&gt; URL rewriting.&lt;br&gt;&lt;br&gt;
✅ Set up &lt;strong&gt;API routes&lt;/strong&gt; to fetch and serve Markdown content.&lt;br&gt;&lt;br&gt;
✅ Optimize your blog for &lt;strong&gt;Agent Experience SEO&lt;/strong&gt; (AI-driven search).&lt;br&gt;&lt;br&gt;
✅ Provide &lt;strong&gt;clean, structured data&lt;/strong&gt; for AI-powered search engines.&lt;/p&gt;



&lt;p&gt;Traditional SEO is no longer enough. AI search engines, &lt;strong&gt;LLM-powered assistants (ChatGPT, Perplexity, Google’s AI Overviews, etc.), and autonomous agents&lt;/strong&gt; are now &lt;strong&gt;indexing&lt;/strong&gt; and &lt;strong&gt;ranking&lt;/strong&gt; content differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does AX-SEO matter?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI agents prefer structured content&lt;/strong&gt; – Raw Markdown is &lt;strong&gt;easier to parse&lt;/strong&gt; than HTML.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LLMs use Markdown for training &amp;amp; retrieval&lt;/strong&gt; – AI search engines extract structured text &lt;strong&gt;more efficiently&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AX-SEO improves discoverability&lt;/strong&gt; – AI-driven platforms rank content &lt;strong&gt;based on how well agents can process it&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want your blog &lt;strong&gt;optimized for AI-driven search&lt;/strong&gt;, this guide is for you!&lt;/p&gt;



&lt;p&gt;Most blogs serve only &lt;strong&gt;HTML&lt;/strong&gt;, making extracting structured information hard for AI tools. Common mistakes include:&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Not offering raw text formats&lt;/strong&gt; – AI agents struggle with unnecessary markup.&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Ignoring structured data for LLMs&lt;/strong&gt; – AI search engines prioritize &lt;strong&gt;clean content&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This guide &lt;strong&gt;avoids these mistakes&lt;/strong&gt; and ensures a &lt;strong&gt;future-proof&lt;/strong&gt; content strategy for AI indexing.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;How I Did It&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Middleware for&lt;/strong&gt; &lt;code&gt;.md&lt;/code&gt; Routing
&lt;/h3&gt;

&lt;p&gt;I used &lt;strong&gt;Next.js Middleware&lt;/strong&gt; to detect &lt;code&gt;.md&lt;/code&gt; URLs and redirect them to an API route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="s2"&gt;next/server&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="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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.md&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;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/api&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rewrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/blog/:path*.md&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/projects/:path*.md&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: API Route to Serve Markdown&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Next, I created API endpoints to fetch Markdown content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readMarkdown&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;@/server/read-markdown-file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&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;next/server&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="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="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;readMarkdown&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Fetching Markdown Content from CMS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;readMarkdown&lt;/code&gt; the function retrieves the raw Markdown content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useBlogSlug&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;@/features/posts/hooks/useBlogSlug&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="s2"&gt;next/server&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readMarkdown&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;markdown&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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;useBlogSlug&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.md&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="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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/plain&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error reading markdown file:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Markdown file not found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&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;h3&gt;
  
  
  &lt;strong&gt;Step 4: Adding a Markdown Link to the Blog&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To make the Markdown file accessible, I added a link on each blog page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/api/&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="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;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="s2"&gt;.md`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;passHref&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  View Markdown
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&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;Now, every post has a &lt;strong&gt;“View Markdown”&lt;/strong&gt; button that links to the raw &lt;code&gt;.md&lt;/code&gt; version.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How This Boosts Agent Experience SEO (AX-SEO)&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;AI-Optimized Content&lt;/strong&gt; – Markdown is &lt;strong&gt;easier for AI bots to read&lt;/strong&gt; than HTML.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;AX-SEO Ready&lt;/strong&gt; – AI-powered search engines &lt;strong&gt;prefer structured text&lt;/strong&gt; for ranking and retrieval.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Faster AI Crawling&lt;/strong&gt; – Lightweight Markdown &lt;strong&gt;improves indexing speed&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Better Content Extraction&lt;/strong&gt; – LLMs can fetch raw text for &lt;strong&gt;RAG-based applications&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Scalable &amp;amp; Future-Proof&lt;/strong&gt; – Works for &lt;strong&gt;blogs, docs, and AI knowledge bases&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;With this approach, I made my &lt;strong&gt;Next.js blog serve Markdown dynamically&lt;/strong&gt;, benefiting both &lt;strong&gt;humans and AI bots&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;📂 &lt;strong&gt;Source Code:&lt;/strong&gt; &lt;a href="https://github.com/smyaseen/smy" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🌍 &lt;strong&gt;Live Website:&lt;/strong&gt; &lt;a href="https://sm-y.dev/" rel="noopener noreferrer"&gt;sm-y.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this guide helps you &lt;strong&gt;boost your blog’s AX-SEO and AI search visibility&lt;/strong&gt;! 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>ai</category>
    </item>
    <item>
      <title>Elevate Your Next.js Security: Middleware Authorization with Userfront</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Sun, 06 Oct 2024 11:10:22 +0000</pubDate>
      <link>https://forem.com/smy/elevate-your-nextjs-security-middleware-authorization-with-userfront-19bk</link>
      <guid>https://forem.com/smy/elevate-your-nextjs-security-middleware-authorization-with-userfront-19bk</guid>
      <description>&lt;p&gt;In this guide, I will show you how to secure your Next.js application with Userfront by implementing middleware-level authorization and leaving component authorization practices.&lt;/p&gt;

&lt;p&gt;Implementing robust security measures like IAM is essential for protecting user data and maintaining compliance. This builds trust with your users and safeguards your application from potential vulnerabilities.&lt;/p&gt;

&lt;p&gt;Many developers overlook comprehensive IAM solutions, opting for basic authentication methods that can expose their applications to significant security risks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Explore Userfront’s features like SSO, multi-tenancy, two-factor authentication, and custom JWTs—all available with a generous free tier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Understand the drawbacks of component-level user authorization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure middleware-level JWT verification for robust authorization.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;As applications grow in complexity, robust security becomes increasingly crucial. Userfront provides a modern IAM solution that integrates seamlessly with Next.js. This guide walks you through integrating Userfront authentication, emphasizing best practices for a secure setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Userfront in the IAM Landscape
&lt;/h2&gt;

&lt;p&gt;Userfront simplifies the authentication process for developers with its easy-to-use SDK. Key features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Sign-On (SSO)&lt;/strong&gt;: Users can log in once and access multiple applications without re-authenticating.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Tenancy&lt;/strong&gt;: Supports multiple clients with a single Userfront account, ideal for SaaS applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Two-Factor Authentication (2FA)&lt;/strong&gt;: Adds an extra layer of security by requiring a second form of verification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SOC 2 Compliance&lt;/strong&gt;: Adheres to strict data privacy and security standards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learn more about Userfront &lt;a href="https://userfront.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Userfront
&lt;/h2&gt;

&lt;p&gt;The Project is already settled up with Userfront. Clone the repository from &lt;a href="https://github.com/smyaseen/userfront-nextjs-middleware" rel="noopener noreferrer"&gt;this link&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To learn about the fundamentals of setting up Userfront with Next.js, refer to the official documentation &lt;/p&gt;

&lt;p&gt;&lt;a href="https://userfront.com/docs/examples/next" rel="noopener noreferrer"&gt;https://userfront.com/docs/examples/next&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Userfront in Your Next.js Application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Environment Variables
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in your project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;WorkspaceId&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//userfront.com/dashboard&lt;/span&gt;
&lt;span class="nx"&gt;NEXT_PUBLIC_USERFRONT_WORKSPACE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Public&lt;/span&gt; &lt;span class="nx"&gt;JWT&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//userfront.com/test/dashboard/jwt?tab=public&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Make&lt;/span&gt; &lt;span class="nx"&gt;sure&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;Base64&lt;/span&gt; &lt;span class="nx"&gt;encoded&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;
&lt;span class="nx"&gt;JWT_PUBLIC_KEY_BASE64&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;login&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;reset&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;signup&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;home&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;dashboard&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;_components&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Directory Breakdown
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;(auth)&lt;/strong&gt;: Contains authentication-related pages (login, signup, reset).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;(public)&lt;/strong&gt;: Public-facing pages (like home) accessible without authentication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;(secure)&lt;/strong&gt;: Pages requiring authentication (like the dashboard).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Component-Level Authorization is Problematic
&lt;/h2&gt;

&lt;p&gt;Consider this approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/(secure)/layout.tsx&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRouter&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;next/navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useUserfront&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;@userfront/next/client&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;SecureLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;children&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="nx"&gt;ReactNode&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&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;isAuthenticated&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;useUserfront&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="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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&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="nx"&gt;isAuthenticated&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="nx"&gt;router&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;isAuthenticated&lt;/span&gt; &lt;span class="o"&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;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;children&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;added a console log to see how it’s going into the secure component everytime and redirects in split second:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExbXhnZmtwMW5kYzA1cm5kNG5zMDF1bXo4ejJyeTFqMW96NXp6dXJsNiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/539jRNQ5yZMtnFBZgk/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExbXhnZmtwMW5kYzA1cm5kNG5zMDF1bXo4ejJyeTFqMW96NXp6dXJsNiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/539jRNQ5yZMtnFBZgk/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redirects&lt;/strong&gt;: Unnecessary redirects and allowing component access for a split second leaving security flaws and bad UX.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Insecure Logic&lt;/strong&gt;: Client-side checks can be manipulated, exposing sensitive data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Race Conditions&lt;/strong&gt;: Delays in loading may expose restricted content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Issues&lt;/strong&gt;: Unnecessary rendering can slow down your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity&lt;/strong&gt;: Mixing authentication logic with UI rendering complicates maintenance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: Harder to manage as the application grows.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Implementing Middleware for Authentication
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;middleware.ts&lt;/code&gt; file for JWT verification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// middleware.ts&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&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="s2"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;jwtVerify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;importSPKI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JWTPayload&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;jose&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;JWT_PUBLIC_KEY_BASE64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_PUBLIC_KEY_BASE64&lt;/span&gt;&lt;span class="o"&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;WORKSPACE_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_USERFRONT_WORKSPACE_ID&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UserFrontJwtPayload&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;JWTPayload&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&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;verifyToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicKeyBase64&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicKey&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;importSPKI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicKeyBase64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RS256&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;payload&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="nf"&gt;jwtVerify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;algorithms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RS256&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;payload&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;UserFrontJwtPayload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JWT verification failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pathsToExclude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(?!\/(&lt;/span&gt;&lt;span class="sr"&gt;api|_next&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;static|favicon&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;ico|manifest|icon|static|mergn&lt;/span&gt;&lt;span class="se"&gt;))&lt;/span&gt;&lt;span class="sr"&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;publicPagesSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/home&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;privatePagesSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/dashboard&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;rootRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/(&lt;/span&gt;&lt;span class="sr"&gt;$|&lt;/span&gt;&lt;span class="se"&gt;\?&lt;/span&gt;&lt;span class="sr"&gt;.+|#.+&lt;/span&gt;&lt;span class="se"&gt;)?&lt;/span&gt;&lt;span class="sr"&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&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;pathsToExclude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;publicPagesSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&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;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`access.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;WORKSPACE_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&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;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;verifyToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JWT_PUBLIC_KEY_BASE64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isAuthenticated&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="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&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="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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="nx"&gt;privatePagesSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&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;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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="nx"&gt;req&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="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isAuthenticated&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;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;see the instant redirect in action:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExc3QweHRoZTB5YjMzMTkyMm1mcWJ3NjR5cWh1bDcyOW84Z2hyazhpeCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/g30Tdv0kvzGQ9NnOWs/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExc3QweHRoZTB5YjMzMTkyMm1mcWJ3NjR5cWh1bDcyOW84Z2hyazhpeCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/g30Tdv0kvzGQ9NnOWs/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Middleware Explained
&lt;/h3&gt;

&lt;p&gt;Middleware processes requests before they reach routes, centralizing authentication logic. Key functions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JWT Verification&lt;/strong&gt;: Ensures only authenticated users can access protected routes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Path Exclusions&lt;/strong&gt;: Optimizes performance by excluding public routes from authentication checks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redirect Logic&lt;/strong&gt;: Manages user redirection based on authentication status.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;By following these steps, you can effectively secure your Next.js application with Userfront's IAM capabilities. Middleware enhances security, ensuring only authorized users access sensitive routes while providing a seamless user experience.&lt;/p&gt;

&lt;p&gt;For more details on the Userfront and its features, visit the Userfront documentation. With Userfront’s generous free tier, you can explore advanced features like SSO, multi-tenancy, and more without any initial investment.&lt;/p&gt;

&lt;p&gt;That’s it! I hope you found this guide helpful. 🚀&lt;/p&gt;

&lt;p&gt;Feel free to follow me on GitHub and LinkedIn for more guides.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/smyaseen" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/sm-y" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Stay awesome and happy coding! ✨&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>security</category>
      <category>userfront</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Maximize Vercel's FREE Plan: Enable Auto Deployment for All Members</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Mon, 30 Sep 2024 03:07:44 +0000</pubDate>
      <link>https://forem.com/smy/maximize-vercels-free-plan-enable-auto-deployment-for-all-members-33ei</link>
      <guid>https://forem.com/smy/maximize-vercels-free-plan-enable-auto-deployment-for-all-members-33ei</guid>
      <description>&lt;p&gt;Earlier, Vercel's free pricing plan allowed multiple members to commit changes that would automatically deploy. However, this feature has recently changed, and now only the project creator can trigger deployments.&lt;/p&gt;

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

&lt;p&gt;To enable this feature for each additional member, a fee of $20 will be charged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bypass the Charge with a GitHub Action
&lt;/h3&gt;

&lt;p&gt;You can create a GitHub Action that performs an empty commit, triggering Vercel to deploy automatically. Here’s how:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create the Workflow File
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Inside your repository, navigate to the &lt;code&gt;.github/workflows&lt;/code&gt; directory. If the &lt;code&gt;workflows&lt;/code&gt; folder doesn't exist, create it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a file named &lt;code&gt;auto-empty-commit.yml&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Add the Script
&lt;/h3&gt;

&lt;p&gt;Paste the following code into &lt;code&gt;auto-empty-commit.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Auto Empty Commit&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;master'&lt;/span&gt; &lt;span class="c1"&gt;# Trigger on pushes to the master branch&lt;/span&gt;
      &lt;span class="c1"&gt;# - '**' # Uncomment to trigger on pushes to any branch&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# Allow write access to repository contents&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;empty_commit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout Repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get the Latest Commit Branch&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get_branch&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "branch=$(git rev-parse --abbrev-ref HEAD)" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create Empty Commit&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config --local user.name "example" # Replace with your name&lt;/span&gt;
          &lt;span class="s"&gt;git config --local user.email "example@example.com" # Replace with your email&lt;/span&gt;
          &lt;span class="s"&gt;git commit --allow-empty -m "Auto commit after push"&lt;/span&gt;
          &lt;span class="s"&gt;git push origin ${{ env.branch }}&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Customization
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Branch Configuration:&lt;/strong&gt; Modify the &lt;code&gt;on.push.branches&lt;/code&gt; section to specify which branch will trigger this action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Git User Configuration:&lt;/strong&gt; Update the Git user name and email in the &lt;code&gt;Create Empty Commit&lt;/code&gt; step with the credentials of the member who created the project on Vercel.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Final Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Commit your changes and push them to your repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, when a commit is made, the action will create an empty commit, triggering Vercel to deploy automatically.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You’ll know the deployment status by the commit icons: a cross ❌ indicates the deployment failed, while a check ✅ shows successful deployment.&lt;/p&gt;

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

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

&lt;p&gt;That’s it! I hope you found this guide helpful. 🚀&lt;/p&gt;

&lt;p&gt;Feel free to follow me on GitHub and LinkedIn for more JavaScript tips and tricks!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/smyaseen" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/sm-y" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Stay awesome and happy coding! ✨&lt;/p&gt;

</description>
      <category>devops</category>
      <category>vercel</category>
      <category>webdev</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>4 Ways to Destructure Array in JavaScript &amp; make your code look clean</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Sun, 11 Aug 2024 09:56:00 +0000</pubDate>
      <link>https://forem.com/smy/4-ways-to-destructure-array-in-javascript-make-your-code-look-clean-gjk</link>
      <guid>https://forem.com/smy/4-ways-to-destructure-array-in-javascript-make-your-code-look-clean-gjk</guid>
      <description>&lt;p&gt;Helloooooooo! 🎉&lt;/p&gt;

&lt;p&gt;I hope you're doing awesome! This is SMY! 👋 Today, we're diving into some cool JavaScript magic with array destructuring! 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  📜 Contents:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;⚡ Wait What?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚡ But Why?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚡ But How?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1️⃣ Destructuring Arrays Chronologically&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;2️⃣ Destructuring Arrays by Index&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;3️⃣ Destructuring Arrays within Objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;4️⃣ Destructuring Arrays with Dynamic Indexes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Wait What?
&lt;/h2&gt;

&lt;p&gt;Array destructuring is a neat feature in JavaScript that allows you to extract values from arrays (or properties from objects) into distinct variables. It’s not just for making your code look cool—it’s about writing cleaner, more readable code. Let’s break down how you can destructure arrays in different ways!&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ But Why?
&lt;/h2&gt;

&lt;p&gt;Destructuring makes your code more concise and expressive. Instead of accessing array elements by their indices, you can directly extract the values into variables. This can simplify your code, reduce errors, and make it easier to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ But How?
&lt;/h2&gt;

&lt;p&gt;Let’s walk through each method of array destructuring with some examples!&lt;/p&gt;




&lt;h3&gt;
  
  
  1️⃣ &lt;strong&gt;Destructuring Arrays Chronologically&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is the most straightforward way to destructure arrays. You match variables to array elements in the order they appear.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fruits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apple&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;mango&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;banana&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;apple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mango&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;banana&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// apple&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mango&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// mango&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;banana&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// banana&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;fruits&lt;/code&gt; array contains three elements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using &lt;code&gt;[apple, mango, banana]&lt;/code&gt;, we destructure the array into three variables, each corresponding to an element in the array, in the same order.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2️⃣ &lt;strong&gt;Destructuring Arrays by Index&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In JavaScript, you can't directly destructure arrays by index within the array literal itself, but you can achieve similar results with a little workaround using &lt;code&gt;Object.entries&lt;/code&gt; or by manually setting values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fruits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apple&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;mango&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;banana&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mango&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;banana&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// apple&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mango&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// mango&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;banana&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// banana&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Here, we use a syntax that mimics destructuring by treating array indices as keys. This is more of a workaround since destructuring by indices isn't directly supported, but the idea is to align array elements with variables through indices.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3️⃣ &lt;strong&gt;Destructuring Arrays within Objects&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can also destructure arrays that are nested within objects. This allows you to target specific elements in nested structures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fruitsPerSeason&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;summer&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;grapes&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;pineapple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;winter&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;kiwis&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;oranges&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;summer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;grape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pineapple&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;winter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;kiwi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fruitsPerSeason&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grape&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// grapes&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pineapple&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pineapple&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kiwi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// kiwis&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// oranges&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fruitsPerSeason&lt;/code&gt; is an object where each property is an array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By destructuring within the object, we extract specific elements from these arrays into distinct variables.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4️⃣ &lt;strong&gt;Destructuring Arrays with Dynamic Indexes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For a more dynamic approach, you can combine destructuring with variables that hold indices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fruitsPerSeason&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;summer&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;pineapple&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;grapes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;winter&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;kiwis&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;oranges&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pineappleIdx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;kiwisIdx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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="na"&gt;summer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pineapple&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;winter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;kiwis&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fruitsPerSeason&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pineapple&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pineapple&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kiwis&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// kiwis&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Here, we’re using &lt;code&gt;_&lt;/code&gt; as a placeholder to ignore the first elements and destructure only the elements we need based on dynamic indices (though indices themselves aren't dynamically used in this example).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrapping Up:
&lt;/h2&gt;

&lt;p&gt;Destructuring arrays can streamline your JavaScript code, making it cleaner and more expressive. Whether you're extracting values chronologically, targeting specific indices, or working within objects, these techniques help you handle arrays more efficiently.&lt;/p&gt;

&lt;p&gt;That’s it, folks! Hope you found this breakdown of array destructuring helpful and insightful. 🚀&lt;/p&gt;

&lt;p&gt;Feel free to follow me on GitHub &amp;amp; LinkedIn for more JavaScript tips and tricks!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/smyaseen" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/sm-y" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Stay awesome and happy coding! ✨&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Automate Your Git Workflows with Git Hooks 🚀</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Sun, 28 Jul 2024 10:10:00 +0000</pubDate>
      <link>https://forem.com/smy/automate-your-git-workflows-with-git-hooks-4ah7</link>
      <guid>https://forem.com/smy/automate-your-git-workflows-with-git-hooks-4ah7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Helloooooooo!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hope you're doing great! This is SMY! 👋 Let's Jump right in 🚀&lt;/p&gt;

&lt;p&gt;....  &lt;/p&gt;

&lt;p&gt;I've settled up an example commit-msg hook that on every commit&lt;/p&gt;

&lt;p&gt;↳ checks for branch name convention i.e [type]/ABC-[ticketnumber]-[objective]&lt;/p&gt;

&lt;p&gt;↳ checks for commit-msg convention i.e [ABC-ticketnumber] [type]: objective&lt;/p&gt;

&lt;p&gt;↳ checks for lints, prettier, and run unit tests&lt;/p&gt;

&lt;p&gt;Gist Link: &lt;a href="https://gist.github.com/smyaseen/17083d60d02a07b2a3122410e2d39b6f" rel="noopener noreferrer"&gt;https://gist.github.com/smyaseen/17083d60d02a07b2a3122410e2d39b6f&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;.....&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;⚡ &lt;code&gt;Wait What?&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚡ &lt;code&gt;But Why?&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚡ &lt;code&gt;But How?&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1️⃣ What -
&lt;/h2&gt;

&lt;p&gt;↳ Git hooks are scripts that run automatically whenever a particular event occurs in a Git repository.&lt;/p&gt;

&lt;p&gt;↳ They let you customize Git’s internal behaviour and trigger customizable actions at key points in the development life cycle.&lt;/p&gt;

&lt;p&gt;↳ There are local hooks and server-side hooks.&lt;br&gt;
 ↳ Local hooks run on your machine and server-side on the remote repository.&lt;/p&gt;

&lt;p&gt;local hooks:&lt;/p&gt;

&lt;p&gt;↳ pre-commit&lt;br&gt;
 ↳ prepare-commit-msg&lt;br&gt;
 ↳ commit-msg&lt;br&gt;
 ↳ post-commit&lt;br&gt;
 ↳ post-checkout&lt;br&gt;
 ↳ pre-rebase&lt;/p&gt;

&lt;p&gt;server hooks:&lt;/p&gt;

&lt;p&gt;↳ pre-receive&lt;br&gt;
 ↳ update&lt;br&gt;
 ↳ post-receive&lt;/p&gt;
&lt;h2&gt;
  
  
  2️⃣ Why -
&lt;/h2&gt;

&lt;p&gt;↳ For example, you want to run Lint checks before files are committed, so we use the pre-commit hook.&lt;/p&gt;

&lt;p&gt;↳ another example you want to enforce the standard branch name and commit-msg convention, so we use the commit-msg hook.&lt;/p&gt;

&lt;p&gt;↳ and lots more...&lt;/p&gt;
&lt;h2&gt;
  
  
  3️⃣ How -
&lt;/h2&gt;

&lt;p&gt;↳ For easy setup, in a JavaScript project, install a library called Husky and follow the documentation &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/husky" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/husky&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;↳ An example is that I want to enforce branch names, commit message convention, and run lint, prettier, and tests.&lt;/p&gt;

&lt;p&gt;↳ We can use multiple hooks. In my case, I will add a commit-msg hook. The reason I haven't chosen pre-commit was that it doesn't check for commit-msg as it runs before commit. I don't want a developer to run checks and fail at commit message, fix, and run all again. I want to check for the commit message first.&lt;/p&gt;

&lt;p&gt;↳ Create a commit-msg hook, following husky's documentation, and paste the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;#!/usr/bin/env sh&lt;/span&gt;
. "$(dirname -- "$0")/_/husky.sh"

&lt;span class="gh"&gt;# Checks for branch name&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;currentBranch=$(git rev-parse --abbrev-ref HEAD)
requiredPattern="^(build|chore|feat|docs|refactor|perf|test)/ABC-&lt;span class="se"&gt;\d&lt;/span&gt;+-.+$"

if ! echo "$currentBranch" | grep -qE $requiredPattern; then
    echo "&lt;span class="se"&gt;\n&lt;/span&gt;Invalid branch name: $currentBranch"
    echo "-"
    echo "Should follow this pattern: build|chore|feat|docs|refactor|perf|test/ABC-ticketnumber-any-text"
    echo "-"
    echo "example: docs/ABC-123-update-readme.md"
    echo "-"
    echo "Refer to this for convention:"
    echo "-"
    echo "build : Changes related to building the code (e.g. adding npm dependencies or external libraries)."
    echo "-"
    echo "chore: Changes that do not affect the external user (e.g. updating the .gitignore file or .prettierrc file)."
    echo "-"
    echo "feat: A new feature."
    echo "-"
    echo "fix: A bug fix."
    echo "-"
    echo "docs: Documentation a related changes."
    echo "-"
    echo "refactor: A code that neither fix bug nor adds a feature."
    echo "-"
    echo "perf: A code that improves performance style: A code that is related to styling."
    echo "-"
    echo "test: Adding new test or making changes to existing test"
    echo "-&lt;span class="se"&gt;\n&lt;/span&gt;"&lt;span class="sb"&gt;

    exit 1  # Branch name doesn't match the pattern, exit with error code
&lt;/span&gt;fi

&lt;span class="gh"&gt;# Checks for commit message&lt;/span&gt;

commit_message="$(cat "$1")"

pattern='^&lt;span class="se"&gt;\[&lt;/span&gt;ABC-[0-9]+&lt;span class="se"&gt;\]&lt;/span&gt; (build|chore|feat|docs|refactor|perf|test): .+$'

if [[ ! $commit_message =~ $pattern ]]; then
    echo "&lt;span class="se"&gt;\n&lt;/span&gt;Invalid commit message: $commit_message"
    echo "-"
    echo "Should follow this pattern: [ABC-ticketnumber] build|chore|feat|docs|refactor|perf|test: objective"
    echo "-"
    echo "example: [ABC-15] chore: updated .gitignore"
    echo "-"
    echo "Refer to this for convention:"
    echo "-"
    echo "build : Changes related to building the code (e.g. adding npm dependencies or external libraries)."
    echo "-"
    echo "chore: Changes that do not affect the external user (e.g. updating the .gitignore file or .prettierrc file)."
    echo "-"
    echo "feat: A new feature."
    echo "-"
    echo "fix: A bug fix."
    echo "-"
    echo "docs: Documentation a related changes."
    echo "-"
    echo "refactor: A code that neither fix bug nor adds a feature."
    echo "-"
    echo "perf: A code that improves performance style: A code that is related to styling."
    echo "-"
    echo "test: Adding new test or making changes to existing test"
    echo "-&lt;span class="se"&gt;\n&lt;/span&gt;"
  exit 1
fi&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="gh"&gt;# npx lint-staged -- uncomment when have lint setted up&lt;/span&gt;
&lt;span class="gh"&gt;# npm run test -- uncomment when have test setted up&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;↳ Now, whenever you commit, it will check for branch and commit naming convention along with running lint checks. Finally, it will run tests in the end, after everything else is good to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  4️⃣ Result -
&lt;/h2&gt;

&lt;p&gt;✨ Consistency.&lt;br&gt;
 ✨ Standardization.&lt;br&gt;
 ✨ Mind Off the Trivial.&lt;br&gt;
 ✨ Automate &amp;amp; Focus on Impactful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up:
&lt;/h2&gt;

&lt;p&gt;We just Elevated Your Development Workflow with a Git Hooks. 🚀&lt;/p&gt;

&lt;p&gt;.....&lt;/p&gt;

&lt;p&gt;Now you can supercharge your development workflow 🚀&lt;/p&gt;

&lt;p&gt;That's it, folks! I hope it was a good read for you. Thank you! ✨&lt;/p&gt;

&lt;p&gt;👉 Follow me&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/smyaseen" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/sm-y" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>git</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Elevate Your Development Workflow with GitHub PR Templates! 🌟</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Tue, 23 Jul 2024 04:59:47 +0000</pubDate>
      <link>https://forem.com/smy/elevate-your-development-workflow-with-github-pr-templates-3k87</link>
      <guid>https://forem.com/smy/elevate-your-development-workflow-with-github-pr-templates-3k87</guid>
      <description>&lt;p&gt;&lt;strong&gt;Helloooooooo!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hope you're doing great! This is SMY! 👋 Let's Jump right in 🚀&lt;/p&gt;

&lt;p&gt;....  &lt;/p&gt;

&lt;p&gt;I've gathered and put together an Extensive PR Template! Feel free to tailor it further to align with your style.  &lt;/p&gt;

&lt;p&gt;Template Link: &lt;a href="https://lnkd.in/djHD24pH" rel="noopener noreferrer"&gt;https://lnkd.in/djHD24pH&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;.....&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Contents:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;⚡ &lt;code&gt;Wait What?&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚡ &lt;code&gt;But Why?&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚡ &lt;code&gt;But How?&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1️⃣ What -
&lt;/h2&gt;

&lt;p&gt;PR templates offer a visual snapshot for reviewers to quickly grasp the essence and state of a pull request. Imagine your team diving into a PR and instantly comprehending its purpose, changes, and necessary actions. That's the magic of a well-structured template.&lt;/p&gt;

&lt;h2&gt;
  
  
  2️⃣ Why -
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Reason 1: Mind Off the Trivial, Focus on Impactful
&lt;/h3&gt;

&lt;p&gt;Say goodbye to mental juggling! Templates serve as a self-checklist, eliminating the need to wrack your brain over remembering small yet crucial details. Instead, channel that mental energy towards crafting exceptional code and solving complex challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 2: Living Documentation
&lt;/h3&gt;

&lt;p&gt;Treat your PR template as a living, breathing document that captures the essence of each change. It's not just about the present; it's a reference point for the future. Easily traceable and understandable, it becomes a valuable resource for anyone peeking into the history of your codebase.&lt;/p&gt;

&lt;p&gt;But wait, there's more! 🌟&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 3: Consistency &amp;amp; Standardization
&lt;/h3&gt;

&lt;p&gt;With PR templates, maintain consistency across your project repositories. Whether you're working on bug fixes, feature enhancements, or other changes, ensure a uniform approach that aligns with your team's best practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 4: Enhanced Communication
&lt;/h3&gt;

&lt;p&gt;These templates aren't just for code; they foster better communication within your team. Express your intentions, highlight potential issues, and open the floor for meaningful discussions—all in one structured format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 5: Effortless Onboarding
&lt;/h3&gt;

&lt;p&gt;Simplify onboarding for new team members by providing a clear blueprint for creating effective pull requests. It's like having a welcome mat that guides them through the team's established processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  3️⃣ How -
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a custom template with Markdown, and name it "PULL_REQUEST_&lt;a href="http://TEMPLATE.md" rel="noopener noreferrer"&gt;TEMPLATE.md&lt;/a&gt;"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste the following example:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Description&lt;/span&gt;

&amp;lt;!--
Please do not leave this blank
This PR [adds/removes/fixes/replaces] the [feature/bug/etc].
--&amp;gt;

&lt;span class="gu"&gt;## What type of PR is this? (check all applicable)&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; [ ] 🍕 Feature - A new feature.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🐛 Bug Fix - self-explanatory
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 📝 Documentation Update - Documentation and related changes.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🎨 Style - Changes that do not affect the meaning of the code; for example, white space, formatting, or missing semicolons.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🧑‍💻 Code Refactor - A code that neither fixes a bug nor adds a feature. (eg: You can use this when there is semantic changes like renaming a variable/ function name).
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🔥 Performance Improvements - A code change that improves performance.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] ✅ Test - Added | Modified | Removed tests
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🤖 Build - Changes related to code building (e.g. adding npm dependencies or external libraries).
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🔁 CI - Changes that affect the build CI/CD pipeline
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 📦 Chore - Changes that do not affect the external user (e.g. updating the .gitignore file or .prettierrc file).
&lt;span class="p"&gt;-&lt;/span&gt; [ ] ⏩ Revert - self-explanatory

&lt;span class="gu"&gt;## Related Tickets &amp;amp; Documents&lt;/span&gt;

&lt;span class="gu"&gt;## Mobile &amp;amp; Desktop Screenshots/Recordings&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Visual changes require screenshots --&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Quality Checklist&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; [ ] 👷‍♀️ Created small PR.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 👴🏻 No deprecated or outdated code is introduced
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 💭 Code is self-documenting. Comments are unnecessary and should only be used to explain why a decision was made
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🗒️ Methods are documented with JS Doc including description, params, and return type
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 📋 The commit message follows our guidelines
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 👌 The pull request description explains any decisions or trade-offs made regarding code quality and design
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🔖 The branch follows our naming guidelines

&lt;span class="gu"&gt;## Self Checklist&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; [ ] 👓 I have followed the style guidelines of this project
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🤳 I have performed a self-review of my code
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🏷️ I have correctly labelled PR &amp;amp; added Ticket Number
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🙆‍♂️ I have cleared the Acceptance Criteria
&lt;span class="p"&gt;-&lt;/span&gt; [ ] ⚠️ My changes generate no new warnings

&lt;span class="gu"&gt;## Added tests?&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; [ ] 👍 yes, new and existing unit tests pass locally with my changes
&lt;span class="p"&gt;  -&lt;/span&gt; [ ] ♻️ had to make changes to existing tests
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🥹 no, because I need help
&lt;span class="p"&gt;  -&lt;/span&gt; [ ] ⏮️ some existing tests are failing
&lt;span class="p"&gt;-&lt;/span&gt; [ ] ⌛ no time to add tests
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🙅 no, because they aren't needed

&lt;span class="gu"&gt;## Added to documentation?&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; [ ] 📜 README.md
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 📝 Confluence
&lt;span class="p"&gt;-&lt;/span&gt; [ ] 🙅 no documentation needed

&lt;span class="gu"&gt;## [optional] Are there any post-deployment tasks we need to perform?&lt;/span&gt;

&lt;span class="gu"&gt;## [optional] What gif best describes this PR or how it makes you feel?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Head to your GitHub repository, select the default branch and make a .git folder at the root.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Put the template in the folder and commit changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, every time someone makes a PR, the template will appear.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrapping Up:
&lt;/h2&gt;

&lt;p&gt;We just Elevated Your Development Workflow with a GitHub PR Template. 🚀&lt;/p&gt;

&lt;p&gt;.....&lt;/p&gt;

&lt;p&gt;Now you can supercharge your development workflow 🚀&lt;/p&gt;

&lt;p&gt;That's it, folks! I hope it was a good read for you. Thank you! ✨&lt;/p&gt;

&lt;p&gt;👉 Follow me&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/smyaseen" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/sm-y" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Seamlessly Transform Your Smart Phone into a Second Screen for FREE with Zero Configuration: Experience Seamless Multitasking!</title>
      <dc:creator>Syed Muhammad Yaseen</dc:creator>
      <pubDate>Sat, 13 Jul 2024 12:22:41 +0000</pubDate>
      <link>https://forem.com/smy/seamlessly-transform-your-smart-phone-into-a-second-screen-for-free-with-zero-configuration-experience-seamless-multitasking-48bk</link>
      <guid>https://forem.com/smy/seamlessly-transform-your-smart-phone-into-a-second-screen-for-free-with-zero-configuration-experience-seamless-multitasking-48bk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Helloooooooo!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hope you're doing great! This is SMY! 👋 Let's Jump right in 🚀&lt;/p&gt;

&lt;p&gt;Although there are other options like physically connecting with adapters or purchasing software like &lt;code&gt;Duet&lt;/code&gt;. But, if you're like me, you would want a seamless &lt;code&gt;Just Work&lt;/code&gt; solution and have a second screen setup in no time.&lt;/p&gt;

&lt;p&gt;That's where &lt;code&gt;Deskreen&lt;/code&gt; comes into play! Follow the steps to easily set up your screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;⚡ &lt;code&gt;Downloading Deskreen&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚡ &lt;code&gt;Sharing your screen and Streaming on Mobile&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Downloading Deskreen
&lt;/h3&gt;

&lt;p&gt;Head over to the following link and download &amp;amp; install &lt;code&gt;Deskreen&lt;/code&gt; for your platform:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deskreen.com/lang-en" rel="noopener noreferrer"&gt;https://deskreen.com/lang-en&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Allowing Deskreen
&lt;/h3&gt;

&lt;p&gt;For Mac users: Allow Screen Recording Permission on MacOS is in System Preferences -&amp;gt; Security &amp;amp; Privacy -&amp;gt; Privacy -&amp;gt; Screen Recording&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzq81aqlfd7q4ve260sua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzq81aqlfd7q4ve260sua.png" alt="Allow Screen Recording Permission on MacOS" width="800" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Windows users: need to add 'Private Network Access' for Deskreen on the first start or in firewall settings&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Connect your Phone
&lt;/h3&gt;

&lt;p&gt;Open up &lt;code&gt;Deskreen&lt;/code&gt; and Connect your Phone by scanning a QR or going to the given address:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbucs1h7bxi1sa4zq1urz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbucs1h7bxi1sa4zq1urz.png" alt="Connect your Phone by scanning a QR" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will automatically ask for approval once you open the page on the Phone's browser.&lt;/p&gt;

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

&lt;p&gt;Click on Allow and your Phone will be connected!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Share your Desired Screen
&lt;/h3&gt;

&lt;p&gt;Once Connected, share your entire screen or desired window:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uxkr3uzjyc1kn52duek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uxkr3uzjyc1kn52duek.png" alt="share your entire screen or desired window" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once done, confirm the options and your screen will be streamed on your Phone!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6s9zvoi4c8p3qaq86870.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6s9zvoi4c8p3qaq86870.png" alt="confirm the options and your screen will be streamed on your Phone!" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf0gk54xyw8vnnogv120.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf0gk54xyw8vnnogv120.png" alt="your screen will be streamed on your Phone!" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up:
&lt;/h2&gt;

&lt;p&gt;We just did the steps to Connect our Screen for Streaming on the Phone's browser. 🚀&lt;/p&gt;

&lt;p&gt;.....&lt;/p&gt;

&lt;p&gt;Now you can Experience Seamless Multitasking 🚀&lt;/p&gt;

&lt;p&gt;That's it, folks! I hope it was a good read for you. Thank you! ✨&lt;/p&gt;

&lt;p&gt;👉 Follow me&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/smyaseen" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/sm-y" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>tooling</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
