<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anju Karanji</title>
    <description>The latest articles on DEV Community by Anju Karanji (@sagi0312).</description>
    <link>https://dev.to/sagi0312</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%2F2718728%2F784f570a-fb63-4241-8ba2-6796d5db175d.JPG</url>
      <title>DEV Community: Anju Karanji</title>
      <link>https://dev.to/sagi0312</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sagi0312"/>
    <language>en</language>
    <item>
      <title>It's over, Repo. I have the high ground!</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Sat, 14 Mar 2026 21:41:49 +0000</pubDate>
      <link>https://dev.to/sagi0312/its-over-repo-i-have-the-high-ground-58md</link>
      <guid>https://dev.to/sagi0312/its-over-repo-i-have-the-high-ground-58md</guid>
      <description>&lt;p&gt;Your boyfriend has messed up. Royally. He knows it. You know it. The neighbor knows it. Everyone and their mother knows it!&lt;br&gt;
The words form in your head -&lt;br&gt;
&lt;em&gt;I&lt;/em&gt;. &lt;em&gt;Told&lt;/em&gt;. &lt;em&gt;You&lt;/em&gt;. &lt;em&gt;So&lt;/em&gt;.&lt;br&gt;
And then, this other voice, "Don't be a dick, Anju" seemingly comes out of nowhere!&lt;br&gt;
And then, dang! You swallow the sentence.&lt;br&gt;
Congratulations. You’re basically Mother Teresa.&lt;br&gt;
Just… hotter.&lt;/p&gt;

&lt;p&gt;Next scenario: The man cuts you off in traffic. Your hand is already on the horn.&lt;br&gt;
A very specific two-word insult involving his mother... is loading. And again: Don't be a dick, Anju.&lt;br&gt;
Hand moves away, curse dies in your throat. You’re Buddha baby! You are practically levitating.&lt;/p&gt;

&lt;p&gt;Or when you’ve crafted the perfect insult.&lt;br&gt;
You know the kind: &lt;em&gt;Elegant&lt;/em&gt;. &lt;em&gt;Perfect&lt;/em&gt;. A gift from the universe. Frame-worthy! &lt;br&gt;
And right before you say it... you get a vision of future-you; rocking back and forth at 2:30 a.m., ruminating, feeling guilty. Forever. Until eternity.&lt;br&gt;
The insult is swallowed. The masterpiece lost to history. Did I mention already? Yes. I &lt;em&gt;am&lt;/em&gt; Jesus.&lt;br&gt;
The Vatican has been notified.&lt;/p&gt;

&lt;p&gt;That voice? That sanctimonious, holier-than-thou voice? &lt;br&gt;
&lt;strong&gt;That's the linter for you!&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Fixing legacy lint errors at work. You know how it goes... you fix one error, you write a blog.
&lt;/h3&gt;

&lt;p&gt;For frontend code, ESLint is the dominant choice.&lt;br&gt;
It's the Obi-Wan Kenobi. Strict older brother energy. But secretly caring.&lt;/p&gt;

&lt;p&gt;Obi-Wan doesn’t live inside the IDE. He lives away from Luke but in the same desert.&lt;/p&gt;
&lt;h3&gt;
  
  
  Let's talk: Job Description.
&lt;/h3&gt;

&lt;p&gt;In VS Code, ESLint parses every debounced keystroke and converts javascript into AST. It takes your tiny little &lt;br&gt;
&lt;code&gt;const x = 1&lt;/code&gt;&lt;br&gt;
and turns it into AST (Nodes. Relationships. Structure... a complete ancestry report). A whole crime scene - over 1 variable. Iconic! 😏&lt;/p&gt;

&lt;p&gt;Before it starts traversing the AST, ESLint's already mapped your codebase into a scope tree (basically tracking which variables live where, and who can access what).&lt;/p&gt;

&lt;p&gt;Each rule registers for the only node type it truly cares about. Very committed. And voila! The listener map is ready.&lt;/p&gt;

&lt;p&gt;During the walk, the listener map applies the rules and these rules with the help of the scope tree decide whether to call &lt;code&gt;report()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Think of it as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If a &lt;em&gt;CallExpression&lt;/em&gt; appears, wake up only &lt;em&gt;RuleA&lt;/em&gt;. Joker walks in, only Batman stands up.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;CallExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ruleA&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;Identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ruleC&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;VariableDeclaration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ruleD&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might already know this part... remember Leetcode? DFS? Visitor pattern? That's the algorithm ESLint uses to walk AST.&lt;/p&gt;

&lt;p&gt;(Your little &lt;code&gt;const x = 1&lt;/code&gt; you ask... triggers nothing.)&lt;br&gt;
ESLint walks past it like: Not today baby!&lt;/p&gt;
&lt;h3&gt;
  
  
  Plugins - the Jedis who do the actual sparring
&lt;/h3&gt;

&lt;p&gt;ESLint itself is more like a sitting member of the jedi council. The Jedis that participate in the clone war, that’s all &lt;em&gt;plugins&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;eslint-plugin-react (Anakin), eslint-plugin-unicorn (Mace Windu), etc...&lt;/p&gt;
&lt;h3&gt;
  
  
  Bienvenido Grogu.
&lt;/h3&gt;

&lt;p&gt;Today, let's write a linter... for the heck of it. &lt;br&gt;
Not &lt;em&gt;the&lt;/em&gt; Obi-Wan. He's seen wars. Just a bite-sized 'baby Yoda'.&lt;/p&gt;

&lt;p&gt;Our force can catch every rogue &lt;code&gt;console.log&lt;/code&gt; left behind in code.  &lt;br&gt;
Here's the thing about Grogu though - he’s not the sharpest tool in the shed.  &lt;br&gt;
Grogu logic goes something like - see a frog → eat the frog.&lt;/p&gt;

&lt;p&gt;It visits every node in the AST and calls report() whenever it finds &lt;code&gt;console.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the whole traversal - super simple&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The traversal accepts AST and the map only bothers itself with 'CallExpression' node. The only Jedi assigned to that node is 'noConsoleLog'.&lt;/span&gt;

&lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;CallExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;noConsoleLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&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;function&lt;/span&gt; &lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Base case: if this isn't a real AST node, return early&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;node&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;node&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If we have a Jedi registered for this node type, fire it&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;visitor&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Recurse through all it's children just to be sure&lt;/span&gt;
  &lt;span class="k"&gt;for &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;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;visitor&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;Grogu only complains. ESLint however &lt;em&gt;is&lt;/em&gt; the adult and so takes care of the clean up if urged. &lt;br&gt;
Pass &lt;code&gt;--fix&lt;/code&gt; and it gathers all the fixes and applies them at the end.&lt;br&gt;
Calling &lt;code&gt;npm link&lt;/code&gt; makes it globally accessible on your machine.&lt;br&gt;
And... that's it. Your very own prickly little conscience is ready to harass your repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Word travels fast 'round these parts. And the word is, there's new kids in town.
&lt;/h3&gt;

&lt;p&gt;Biome and Oxlint are written in Rust. On a 1,000-file repo, ESLint might take 40 seconds. Oxlint does it in under 2s flat! Reason being ESLint is JavaScript. So, single-threaded.&lt;/p&gt;

&lt;p&gt;These new plugin ecosystems are however still catching up. I tried Biome on a personal project and liked it. It is worth your time. YouTube has solid tutorials if you want to go deeper. I like this one - &lt;a href="https://www.youtube.com/watch?v=x5kwmIaPty8&amp;amp;t=48s" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=x5kwmIaPty8&amp;amp;t=48s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just fyi, ESLint &lt;em&gt;did&lt;/em&gt; hold the fort down for 13 years (So that kind of time does help you load up on ammunition)&lt;/p&gt;

&lt;h3&gt;
  
  
  In a nutshell:
&lt;/h3&gt;

&lt;p&gt;Linters don't cut you off at the bar. They just hold your hair back while you vomit.&lt;/p&gt;

&lt;p&gt;Baby linter repo is &lt;a href="https://github.com/sagi0312/my-linter" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Grogu is thriving.&lt;br&gt;
I sent the drunk text.&lt;br&gt;
We don't talk about it.&lt;br&gt;
Linter agrees.&lt;br&gt;
Ship the code!👩‍💻&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>eslint</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Code-ing in a Tree: Adding Auto-Save to freeCodeCamp</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Fri, 16 Jan 2026 04:23:59 +0000</pubDate>
      <link>https://dev.to/sagi0312/code-ing-in-a-tree-adding-auto-save-to-freecodecamp-137b</link>
      <guid>https://dev.to/sagi0312/code-ing-in-a-tree-adding-auto-save-to-freecodecamp-137b</guid>
      <description>&lt;p&gt;freeCodeCamp and Anju, sitting in a tree, code-ing (the &lt;em&gt;e&lt;/em&gt; stays. I will die on this hill).&lt;br&gt;
First came ADHD. Then came coffee.&lt;br&gt;
Then—inevitably—a pull request and this blog you are currently reading.  &lt;/p&gt;

&lt;p&gt;After they set the start date for my next gig—about two weeks out—I suddenly had time to burn.&lt;br&gt;
I finished the onboarding docs, cooked actual food, paid the bills, watched some Jimmy Kimmel.&lt;/p&gt;

&lt;p&gt;Eventually, I decided to do some coding—lest I find myself vacuuming the bathroom ceiling out of sheer boredom.&lt;/p&gt;

&lt;p&gt;I poured myself a cup of coffee — still too early for the wine.&lt;/p&gt;

&lt;p&gt;Opened VS Code.&lt;/p&gt;

&lt;p&gt;I stared out the window.&lt;br&gt;
Stared at my coffee.&lt;br&gt;
Watched more Jimmy Kimmel.&lt;/p&gt;

&lt;p&gt;All in the hope that a brilliant app idea would magically appear.&lt;/p&gt;

&lt;p&gt;It didn’t.&lt;/p&gt;

&lt;p&gt;That’s when I decided to go looking for “help wanted” signs on GitHub repos.&lt;/p&gt;

&lt;p&gt;So, I slithered my way back into the freeCodeCamp repo. I am, if nothing else, a creature of familiarity.   &lt;/p&gt;

&lt;p&gt;I did a quick “eeny, meeny, miny, mo” and clicked on one. A small flutter followed, and I knew I’d found the one. Thank God—my Dyson was moments away from meeting the popcorn ceiling.&lt;/p&gt;

&lt;p&gt;So, to cut a long story short, I present to you: &lt;strong&gt;THE ISSUE&lt;/strong&gt;. (Here’s the original issue for context, if you’re curious-&lt;a href="https://github.com/freeCodeCamp/freeCodeCamp/issues/57818" rel="noopener noreferrer"&gt;https://github.com/freeCodeCamp/freeCodeCamp/issues/57818&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cue trumpet music. &lt;/em&gt; &lt;/p&gt;

&lt;p&gt;freeCodeCamp doesn't autosave to localStorage. Users have to hit Ctrl+S. &lt;strong&gt;But here's the problem — nobody tells them that&lt;/strong&gt;. So they write beautiful, gorgeous code, navigate away to watch some Netflix, come back, and discover their masterpiece has been sent to the shadow realm. Ctrl+Z can't save you here. Nothing can.&lt;/p&gt;

&lt;p&gt;My solution was simple: add autosave—the way LeetCode and GreatFrontend already do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/freeCodeCamp/freeCodeCamp/pull/65137" rel="noopener noreferrer"&gt;You can check out the full PR here&lt;/a&gt; if you want to see the implementation details.&lt;/p&gt;

&lt;p&gt;So, after the usual forking and branching, I went hunting for the component in question. Channeling my inner High Potential’s Morgan Gillory, I found the right components surprisingly quickly.&lt;/p&gt;

&lt;p&gt;Turns out 10,000 hours of TV viewing does pay dividends.&lt;/p&gt;

&lt;p&gt;All jokes aside, the folder structure was intuitive. The function names were descriptive and the hunt was fairly straightforward.&lt;/p&gt;

&lt;p&gt;I remember chatting with a Netflix engineer once. She sized me up and said, "You probably design applications backend-first, don't you?" She was right—I do. But this time? I wanted to start with something the user could see. A little visual reassurance felt like the right move. So I added a simple indicator to the toolbar (ActionRow): a FontAwesome checkmark and a quick line of text. Nothing flashy—just enough to whisper, hey, your work is safe.&lt;/p&gt;

&lt;p&gt;You know—I’m a creature of familiarity. My go-to has always been React’s Context API or, more recently, Zustand. Redux was new territory, so I had Claude walk me through the setup - ’lastSavedTime’ was going to be used to calculate the time lapsed since the last save.  &lt;/p&gt;

&lt;p&gt;I checked all the boxes on my mental TODO list:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Persistence to localStorage, wired into debounced onChange, onBlur, onUnmount, and beforeunload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A timestamp that updates every five seconds and resets cleanly on navigation—no stale “Saved 20m ago” ghosts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A big beautiful download button. Big enough to spot from Mars.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Respect for the DRY, courtesy of a shared utility function and a custom hook.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then the tests broke.&lt;br&gt;
&lt;em&gt;Of course they did.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First up: the unit test in &lt;code&gt;completion-modal.test.tsx&lt;/code&gt;. I’m blaming Robert Martin and &lt;em&gt;Clean Code&lt;/em&gt; for this one—I had refactored the logic into a utility and forgotten to update the test. An easy fix.&lt;/p&gt;

&lt;p&gt;Then the e2e tests failed. Two tests in &lt;code&gt;multifile-cert-projects.spec.ts&lt;/code&gt;. Running e2e tests locally felt oddly familiar. Playwright isn’t all that different from Cypress, which I’d used before, and that familiarity helped me zero in on the real issue. The fix turned out to be simple—and, honestly, better design.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Auto-save should be silent.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I updated &lt;code&gt;code-storage-epic.js&lt;/code&gt; to suppress flash messages for auto-saves. Manual saves still get explicit confirmation; auto-saves just quietly update the timestamp. Less noise, and better UX.  &lt;/p&gt;

&lt;p&gt;My PR was officially ready. &lt;br&gt;
&lt;strong&gt;The damage report:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Days spent: 2&lt;br&gt;
Coffee consumed: A few hundred gallons&lt;br&gt;
Fat-Cat cuddles: Stole a few (unless she pushed my face away with her paw)&lt;br&gt;
Showers taken: 0 (for the environment, obviously!)&lt;br&gt;
Lessons learned: Redux isn't scary. &lt;em&gt;Auto-save should whisper, not be a drama queen&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now? I wait. And maybe shower.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update (February 2026):
&lt;/h3&gt;

&lt;p&gt;I waited… For 1.5 months.&lt;/p&gt;

&lt;p&gt;One maintainer surfaced briefly, commented that “the implementation is solid,” but wasn't sure if they wanted the feature. They tagged decision-makers for input.&lt;/p&gt;

&lt;p&gt;Then? Radio silence.&lt;/p&gt;

&lt;p&gt;I nudged politely every few weeks.&lt;/p&gt;

&lt;p&gt;Meanwhile, the codebase kept evolving. Merge conflicts spawned and I fixed them once. Then they came back. Again. 985 other people were also committing code while my PR quietly fossilized.&lt;/p&gt;

&lt;p&gt;After 1.5 months of limbo - no feedback, no decision - I closed it.&lt;/p&gt;

&lt;h4&gt;
  
  
  What I learned:
&lt;/h4&gt;

&lt;p&gt;Open source contribution is about timing and luck. Sometimes you do everything right and still get ghosted harder than a Tinder match.&lt;/p&gt;

&lt;p&gt;But I don't regret it. I learned Redux and playwright, and I got this blog post out of it. The feature works. The code is solid.&lt;/p&gt;

&lt;p&gt;Not every PR merges. But every PR teaches you something - Like maybe shower occasionally.&lt;/p&gt;

&lt;p&gt;So I consider that a win.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>From CDN to Pixel: A React App's Journey</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Thu, 08 Jan 2026 22:35:18 +0000</pubDate>
      <link>https://dev.to/sagi0312/from-cdn-to-pixel-a-react-apps-journey-4dnd</link>
      <guid>https://dev.to/sagi0312/from-cdn-to-pixel-a-react-apps-journey-4dnd</guid>
      <description>&lt;p&gt;The success of my last blog has cursed me with the burden of EXPECTATIONS. I've accidentally set the bar too high and now have to pretend I'm good at this. To cope with this crushing pressure, I’ve turned to the most emotionally stable things in my life: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wine &lt;/li&gt;
&lt;li&gt;Hallmark Christmas movies where small towns have better WiFi than my house.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[&lt;em&gt;Originally drafted in December. Finally committed in January. Yes - Procrastination is my brand.&lt;/em&gt; 😌]&lt;/p&gt;

&lt;p&gt;Four movies deep into "Career-oriented big City Girl falls for handsome small town tree farmer who saves her from personal or professional ruin", I remember: oh right - I have a React blog to write.  &lt;br&gt;
And then I thought: God, I wish React were more like the ruggedly handsome Christmas-tree-farm guy with the flannel shirt and the jawline. &lt;em&gt;sigh&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Steady. Predictable. Doesn't have a meltdown because someone three counties over changed their order about pie flavors.&lt;/p&gt;

&lt;p&gt;Also — and I cannot stress this enough — devastatingly handsome.&lt;/p&gt;

&lt;p&gt;React's whole brand is "I’m the stable, predictable framework. I make UI updates easy.”&lt;/p&gt;

&lt;p&gt;LIES! ABSOLUTE LIES I SAY!&lt;/p&gt;

&lt;p&gt;He will re-render because his cousin’s, ex-girlfriend’s props changed even though he hasn’t spoken to that cousin since Thanksgiving ’09 or - just because you made eye contact.&lt;/p&gt;

&lt;p&gt;React whispers sweet nothings like "I'm just a library standing in front of a dev, asking her to love me" and then casually mentions you'll need React Router, React Query, React Hook Form, and 47 other "react-something" packages - not his problem.&lt;/p&gt;

&lt;p&gt;So in the spirit of holiday romance — and my heart's desire to understand his backstory, I present to you:&lt;/p&gt;

&lt;p&gt;From CDN to Pixel: A React App’s Journey from "npm run build" to "oh look, a button"&lt;/p&gt;

&lt;p&gt;The Browser (let's call her... Browser) arrives in town, confident and capable. She's been rendering content since 1995. She's parsed HTML that would make you weep. She's survived the IE6 era. She's seen some stuff.&lt;/p&gt;

&lt;p&gt;She can handle anything.&lt;/p&gt;

&lt;p&gt;Then she meets React.&lt;/p&gt;

&lt;h2&gt;
  
  
  And So it Begins...
&lt;/h2&gt;

&lt;p&gt;Browser types &lt;code&gt;www.small-town-love-story.com&lt;/code&gt; and hits Enter.&lt;br&gt;
DNS resolves to Netlify's CDN. Geography decides the rest - Dallas browser hits Dallas edge, London hits London. Same IP, different physical server (Anycast routing). &lt;/p&gt;

&lt;p&gt;Encrypted connection established.&lt;/p&gt;

&lt;p&gt;This is the Hallmark prelude - the editor ultimatum, the rushed flight home, the "I'm only here for the holidays" trope.&lt;/p&gt;

&lt;p&gt;CDN edge responds with cached &lt;code&gt;index.html&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser Meets index.html
&lt;/h2&gt;

&lt;p&gt;She makes her first friend in town. Naturally, she owns the only café that exists in this town.&lt;/p&gt;

&lt;p&gt;It's empty right now.&lt;br&gt;
Mostly just a &lt;code&gt;&amp;lt;div id="root"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; but it's got potential...&lt;/p&gt;

&lt;p&gt;"I'm a container." index.html says cheerfully. "Once React gets here, this place is gonna be bustling!"&lt;/p&gt;

&lt;p&gt;"We need to save the town Christmas party." she tells Browser. Of course. Duh! The obligatory catastrophe.&lt;/p&gt;

&lt;p&gt;React is still en route from the CDN - packed in those JavaScript files, probably bringing his entire component tree as carry-on.&lt;/p&gt;

&lt;p&gt;Winter is coming...&lt;/p&gt;

&lt;h2&gt;
  
  
  React Finally Shows Up
&lt;/h2&gt;

&lt;p&gt;Cue the slow-motion entrance.&lt;/p&gt;

&lt;p&gt;Hair blowing in non-existent wind. Flannel shirt unbuttoned just enough. &lt;br&gt;
And the abs. &lt;br&gt;
The &lt;em&gt;glorious&lt;/em&gt; abs.&lt;/p&gt;

&lt;p&gt;Browser's JavaScript engine parses ~170KB of bundles. &lt;br&gt;
Parse time: ~80-100ms. &lt;br&gt;
Single-threaded. &lt;br&gt;
Blocking.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This&lt;/em&gt; is why bundle size matters - not download time (CDNs are fast), but parse time. Every kilobyte is CPU work grinding away on the main thread while nothing else can happen.&lt;/p&gt;

&lt;p&gt;He spots that empty &lt;code&gt;&amp;lt;div id="root"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;"I'll take it from here," he announces, rolling up his sleeves.&lt;/p&gt;

&lt;p&gt;Browser, who's been busy with DNS resolution, TLS handshakes, HTML parsing, and resource orchestration - of course feels the unmistakable pull toward the ruggedly handsome protagonist with the heart of gold. &lt;/p&gt;

&lt;p&gt;Don't roll your eyes people! It &lt;em&gt;is&lt;/em&gt; a rom-com! What else did you expect?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Town Shows Up (Or: How the Christmas Party Actually Gets Saved)
&lt;/h2&gt;

&lt;p&gt;So, now to avert the impending apocalypse, our protagonist React rallies the super-friendly townsfolk.&lt;/p&gt;

&lt;p&gt;He's got the vision. The coordination. The &lt;em&gt;jawline&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But it takes the whole town to actually make it happen.&lt;/p&gt;

&lt;p&gt;JavaScript Engine shows up first — runs React’s code, schedules tasks, queues microtasks, and keeps the main thread alive.&lt;/p&gt;

&lt;p&gt;Rendering Engine does the real construction — creates actual DOM nodes (C++ objects in memory), parses CSS, assembles the render tree by combining DOM + CSSOM.&lt;/p&gt;

&lt;p&gt;Layout Engine measures everything — exact sizes, positions, box model math, flexbox negotiations, grid calculations. Nothing is guessed. This is reflow and it's expensive.&lt;/p&gt;

&lt;p&gt;Paint rasterizes to pixels. Until this moment, nothing was visible. Just data structures.&lt;/p&gt;

&lt;p&gt;Compositor breaks the page into layers, hands them to the GPU — transforms, opacity, z-index. Aims for 60fps.&lt;/p&gt;

&lt;p&gt;The OS, our mayor, gives the final blessings — input events, thread scheduling, screen refresh.&lt;/p&gt;

&lt;p&gt;Pixels hit the screen.&lt;br&gt;
The title "Once Upon a Holiday" fades in.&lt;br&gt;
Okay, she thinks. Maybe he's not completely useless.&lt;br&gt;
The abs certainly don't hurt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Tiff: React's Re-render Philosophy
&lt;/h2&gt;

&lt;p&gt;It’s been a few days.&lt;br&gt;
The title looks cute in its cursive font.&lt;br&gt;
The town has settled. Our couple has routines.&lt;/p&gt;

&lt;p&gt;Then a user clicks a button.&lt;br&gt;
State changes. &lt;br&gt;
React panics.&lt;br&gt;
He re-renders everything.&lt;/p&gt;

&lt;p&gt;"The counter went from 0 to 1," Browser says, very calmly. "Why are you calling &lt;em&gt;every&lt;/em&gt; component function again?"&lt;br&gt;
"Re-renders are cheap. It's just JavaScript," React shrugs.&lt;br&gt;
"I have to recalculate layout. Repaint pixels. Composite layers." Browser's voice tightens. "You just re-rendered 47 components to change one text node."&lt;br&gt;
"Declarative updates," React says defensively. "Simple. Predictable."&lt;br&gt;
"Simple for &lt;em&gt;you&lt;/em&gt;. I'm doing the actual work."&lt;br&gt;
React looks away. She's mad.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;The Big Fight&lt;/strong&gt;™.&lt;/p&gt;

&lt;p&gt;(&lt;em&gt;Hallmark fights, am I right?&lt;/em&gt; 🙄 &lt;em&gt;In production this wouldn’t even log a warning.&lt;/em&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser Packs Her Bags
&lt;/h2&gt;

&lt;p&gt;A few days later, Browser is at the train station, suitcase packed.&lt;br&gt;
"I have other apps to render," she tells index.html. "Other frameworks to work with. This was... temporary"&lt;br&gt;
React shows up breathless. Hair still perfect - obviously.&lt;/p&gt;

&lt;p&gt;"Wait!"&lt;/p&gt;

&lt;p&gt;Browser turns. "What now? Did you bring your 47 npm packages to say goodbye?"&lt;/p&gt;

&lt;p&gt;"I've been working on something," React says. "Memoization."&lt;br&gt;
Browser blinks.&lt;br&gt;
"React.memo. useMemo. useCallback." He's talking fast. "I can skip re-renders now. Only update what actually changed. Like you kept telling me to do."&lt;br&gt;
"And there's more!" React continues. "React Compiler. Automatic memoization. I don't even have to think about optimization anymore. It just... happens."&lt;/p&gt;

&lt;p&gt;She likes this.&lt;/p&gt;

&lt;p&gt;"Sixty frames per second?" she asks.&lt;br&gt;
"Sixty," React promises. "Even under pressure."&lt;/p&gt;

&lt;p&gt;Browser sets the suitcase down.&lt;br&gt;
They kiss.&lt;/p&gt;

&lt;p&gt;Before you gag — a reminder:&lt;br&gt;
it &lt;em&gt;is&lt;/em&gt; a rom-com.&lt;/p&gt;

&lt;h2&gt;
  
  
  6 Months Later
&lt;/h2&gt;

&lt;p&gt;React didn’t become perfect.&lt;br&gt;
Browser didn’t stop doing all the work.&lt;/p&gt;

&lt;p&gt;But now they understand each other.&lt;br&gt;
Snow falls softly over the town.&lt;br&gt;
Fade to black.&lt;br&gt;
&lt;em&gt;(Post-credits scene: someone forgets a dependency array.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>programming</category>
      <category>webdev</category>
      <category>performance</category>
    </item>
    <item>
      <title>React 19.2: React in its sigma era</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Wed, 12 Nov 2025 03:46:02 +0000</pubDate>
      <link>https://dev.to/sagi0312/react-192-react-in-its-sigma-era-op7</link>
      <guid>https://dev.to/sagi0312/react-192-react-in-its-sigma-era-op7</guid>
      <description>&lt;p&gt;The lights dim — or maybe that's just dark mode — and somewhere buried inside a million open tabs, I, React 19.2, take a deep breath. &lt;/p&gt;

&lt;p&gt;I'm the millennial dev of frameworks: experienced, over-caffeinated, quietly wondering if work-life balance is real, and still feeling guilty about using PTO. The stickers still sell, but the critics? They've been whispering for years about "side effects" and "memoization fatigue."&lt;/p&gt;

&lt;p&gt;But I'm back — bolder, wiser, and dare I say, with a little rizz.&lt;/p&gt;

&lt;p&gt;I've stopped taking photos of my meals, swapped Red Bull for matcha, and finally learned to set boundaries with useEffect. &lt;/p&gt;

&lt;p&gt;My new name? React 19.2. And I've finally embraced my sigma era.&lt;/p&gt;

&lt;p&gt;Sure, my new React Compiler (with its Babel plugin) might tack a few seconds onto the Vite build, but that's a small price to pay for the hours you used to spend manually memoizing everything. Isn't it? My compiler now handles optimization automatically — and honestly? I'm stoked about this upgrade.&lt;/p&gt;

&lt;p&gt;What's new in my glow-up:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1) &lt;code&gt;&amp;lt;Activity /&amp;gt;&lt;/code&gt; = "It’s giving background character energy." 🎭&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Okay, real talk — I used to have a toxic push-pull relationship with my components.&lt;br&gt;
Mount. Unmount. Mount again.&lt;br&gt;
It was giving on-again-off-again couple energy.&lt;/p&gt;

&lt;p&gt;One second your &lt;code&gt;&amp;lt;Sidebar /&amp;gt;&lt;/code&gt; was here — the next? Gone. Deleted. State obliterated. Then we’d get back together and I’d have to rebuild everything from scratch like nothing ever happened. Exhausting. For both of us.&lt;/p&gt;

&lt;p&gt;But I’ve grown. With &lt;code&gt;&amp;lt;Activity /&amp;gt;&lt;/code&gt;, I’ve learned that not every break needs to be a breakup.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Activity&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isShowingSidebar&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;visible&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;hidden&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;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Sidebar&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Activity&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React renders &lt;code&gt;&amp;lt;Sidebar /&amp;gt;&lt;/code&gt; in the background at low priority — like NPCs waiting for you to walk by again. State intact, DOM preserved, just off-screen. Not unmounted, just &lt;em&gt;hidden&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It’s giving “we’re on a break but you can still have my Netflix login.”&lt;br&gt;
So very emotionally available 😉&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;2) useEventEffect = "the Gen-Z stare" (boundaries, no oversharing) 🧘‍♀️&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My useEffects -&amp;gt; Every little prop change? Every callback tweak? Boom, dependency drama. I’d drag everyone into my business like, "If I’m re-rendering, we’re all re-rendering."&lt;br&gt;
But then I met useEventEffect.&lt;br&gt;
Cool, detached, emotionally stable — basically the Gen-Z friend who just blinks at your chaos and says, "that’s crazy, lol."&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;onConnected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEventEffect&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;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My new friend - useEventEffect taught me that not every update is about me.&lt;br&gt;
Sometimes, the healthiest thing you can do... is just take it easy... 🧘‍♀️&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;3) cacheSignal = "the friend who cancels plans before you can." 🫠&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Okay, let’s be honest — &lt;code&gt;cacheSignal()&lt;/code&gt; is... fine.&lt;br&gt;
Basically, it gives you an AbortSignal tied to your cached Server Component fetches. So if React decides mid-render that it doesn't need that cached data anymore, the signal aborts and your fetch bails early.&lt;/p&gt;

&lt;p&gt;Real talk: I added it to the list because it's new, not because you'll reach for it. This is the API equivalent of meal-prepping on Sunday and then ordering takeout anyway by Wednesday.&lt;/p&gt;

&lt;p&gt;Is it useful? Sure, in some edge case on a high-traffic app with complex streaming SSR.&lt;br&gt;
Will you use it? Probably not. And that's okay. Not all my kids turned out equally awesome. 😉&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;4) Performance Tracks = "Spotify Wrapped, but for your renders" 📊&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Look, debugging React performance used to be like trying to figure out why your situation-ship ghosted you. Was it me? Did I re-render too much? Am I being needy?&lt;/p&gt;

&lt;p&gt;You'd stare at flame graphs like they were Instagram stories, wondering if 47ms was "a lot" or if you were just being dramatic.&lt;/p&gt;

&lt;p&gt;But now? I'm serving receipts.&lt;/p&gt;

&lt;p&gt;Open Chrome DevTools → Performance tab, and I'll literally show you.&lt;/p&gt;

&lt;p&gt;⚛️ Scheduler Tracks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Blocking track: "Yeah, I froze your UI for 500ms. You asked me to!" (It's not me. It's definitely YOU!)&lt;/li&gt;
&lt;li&gt;Transition track: "This work? Low priority. Multitasking like Snoop Dogg with his side hustles."&lt;/li&gt;
&lt;li&gt;Suspense track: "Still loading that API. I'm being patient, okay!"&lt;/li&gt;
&lt;li&gt;Idle track: "Literally doing busywork. It's giving unemployment"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;⚛️ Components Track:&lt;/p&gt;

&lt;p&gt;The component tree where render time is on full display. Every component gets a colored bar. &lt;br&gt;
Darker = slower = that's your problem child 🤷🏻‍♀️&lt;/p&gt;

&lt;p&gt;I'm no longer bottling things up. I'm communicating. I'm vulnerable. I'm showing you the work.&lt;/p&gt;

&lt;p&gt;And honestly? It's exhausting being this self-aware. 💅&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;5) Partial Pre-rendering = "I do meal prep now!" 🍱&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Partial Pre-rendering sounds delicious, but the recipe isn’t exactly HelloFresh yet. The core API exists in React 19.2, but real-world setup still depends on your framework and server, so the "how" feels a little fuzzy to me.&lt;/p&gt;

&lt;p&gt;PPR in 30 seconds (plain React):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build (or precompute) time: call &lt;code&gt;prerender(&amp;lt;App/&amp;gt;, { signal })&lt;/code&gt; -&amp;gt; you get a prelude (static shell) and a postponed state. Save postponed somewhere (KV/blob/db) and ship prelude to your CDN.  ￼&lt;/li&gt;
&lt;li&gt;Request time: load the saved postponed, then resume the render and stream the dynamic parts into the response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The catch? You're wiring up your own SSR server, managing state storage, configuring everything, and handling hydration. It is a little bit like plumbing I guess.&lt;/p&gt;

&lt;p&gt;With Next.js 15, you can just wrap the dynamic bits in &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt;, flip &lt;code&gt;experimental.ppr = true&lt;/code&gt; in your config, and call it a day. Next does the rest —&amp;gt; less cooking, more eating.&lt;/p&gt;

&lt;p&gt;Again, not exactly the brightest of the bunch — unless you’re using a framework to babysit it.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;6) Batching Suspense Boundaries for SSR = "group therapy for my loading states" 🤝&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I used to have no chill during SSR. I now batch my Suspense boundaries during SSR, meaning I reveal multiple async chunks together instead of one at a time.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LoadingProfile&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Profile&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LoadingPosts&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Posts&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before: Profile flashes in, Posts follows awkwardly later.&lt;br&gt;
Now: I wait till both are ready, then enter the stage gracefully, in sync.&lt;/p&gt;

&lt;p&gt;I’ve grown past my biases. I’m no longer a &lt;em&gt;component-ist&lt;/em&gt; okay? All are equal under the law (which, obviously, is just me 😁)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;🏅 Honorable Mentions:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt; v6:&lt;/strong&gt; This one understands &lt;code&gt;useEffectEvent&lt;/code&gt;, supports flat config by default, and keeps your dependency arrays drama-free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;useId prefix update:&lt;/strong&gt; Changed from &lt;code&gt;:r:&lt;/code&gt; to &lt;code&gt;_r_&lt;/code&gt; to support View Transitions API. If you're doing SSR and using useId() for accessibility (instead of nanoid like a normal person), this matters. Otherwise, carry on. 😁&lt;/p&gt;

&lt;p&gt;React 19.2: optimized, hydrated, emotionally regulated. &lt;strong&gt;Sigma era achieved. 💅&lt;/strong&gt;&lt;br&gt;
Now go build something. I'll be here, compiling in the background, quietly judging your useEffect dependencies 😉&lt;/p&gt;

</description>
      <category>react</category>
      <category>humor</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>React and the City ⚔️ Part 3: Return of the MCP</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Fri, 24 Oct 2025 07:37:34 +0000</pubDate>
      <link>https://dev.to/sagi0312/react-and-the-city-part-3-return-of-the-mcp-1ede</link>
      <guid>https://dev.to/sagi0312/react-and-the-city-part-3-return-of-the-mcp-1ede</guid>
      <description>&lt;h2&gt;
  
  
  ⚡️ Part 3: When Your AI Helps You Integrate... Another AI
&lt;/h2&gt;

&lt;p&gt;FIELD NOTE&lt;/p&gt;

&lt;p&gt;Two MCP servers purring on localhost like they own the place.&lt;br&gt;
Claude Desktop conducting the symphony.&lt;br&gt;
Me at 2 AM, wearing yesterday's hoodie, convinced I've achieved enlightenment.&lt;br&gt;
🧘🏽‍♀️ Narrator: She had not.&lt;/p&gt;

&lt;p&gt;So there I was, watching two MCP servers hum contentedly, when I realized: My Next.js app still wasn’t part of the conversation.  &lt;/p&gt;

&lt;p&gt;So I did what any reasonable developer does at 2 AM — opened Claude and typed the most dignified technical query of my career: "Help. Plz. Make thing talk to other thing."&lt;/p&gt;
&lt;h3&gt;
  
  
  🤝 The Pair-Programming Dance
&lt;/h3&gt;

&lt;p&gt;What followed was the most delightful pair programming session where an AI helped me integrate... another AI. Meta? Absolutely. Effective? You have no idea. Slightly concerning for the future of humanity? We'll cross that bridge when the &lt;em&gt;robots tell us to&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Plot twist: the fancy server.tool() wrapper everyone talks about? Didn't work. &lt;br&gt;
So I rolled up my sleeves and went full grease-monkey with &lt;em&gt;CallToolRequestSchema&lt;/em&gt;, &lt;em&gt;ListToolsRequestSchema&lt;/em&gt; — the raw MCP APIs.&lt;br&gt;&lt;br&gt;
Suddenly I wasn't writing React; I was rebuilding the Millennium Falcon's hyperdrive while Chewie (Claude) gave me encouraging but technically vague advice.&lt;/p&gt;
&lt;h3&gt;
  
  
  🧰 First Challenge: Teaching Next.js to Talk MCP
&lt;/h3&gt;

&lt;p&gt;I needed to spawn my MCP server as a child process.&lt;br&gt;&lt;br&gt;
Added a &lt;strong&gt;bin&lt;/strong&gt; entry in &lt;em&gt;package.json&lt;/em&gt; so &lt;em&gt;npx component-tree-services&lt;/em&gt; could invoke it — basically letting npm drop a symlink in &lt;em&gt;node_modules/.bin/&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"bin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"component-tree-services"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./build/src/index.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Next.js could whisper sweet JSON into my MCP server’s socket.&lt;/p&gt;

&lt;h3&gt;
  
  
  💃 Step by Step: The 5-Line Rule
&lt;/h3&gt;

&lt;p&gt;By this point I was deep in pair-programming with Claude.&lt;/p&gt;

&lt;p&gt;Claude: "Okay, first let's import the dependencies—"&lt;br&gt;
Me: "STOP. Just the imports."&lt;br&gt;
Claude: "Here are the four import lines—"&lt;br&gt;
Me: "Perfect. Next five."&lt;/p&gt;

&lt;p&gt;And so it went. Slow, methodical, and shockingly peaceful — like meditation, but with TypeScript errors.&lt;/p&gt;

&lt;p&gt;When something broke (and oh, things broke), I knew exactly which five lines to blame. No more spelunking through 200 lines of stack traces.&lt;/p&gt;

&lt;p&gt;Me: "Wait — I need an API key?"&lt;br&gt;
Claude: "Yes."&lt;br&gt;
Me: "I have to PAY for this?"&lt;br&gt;
Claude: "Yes."&lt;br&gt;
Me: "With MONEY?"&lt;/p&gt;

&lt;p&gt;I stared at my $7 oat milk latte. Then at my screen. Then back at the latte.&lt;/p&gt;

&lt;p&gt;We proceeded.&lt;/p&gt;

&lt;p&gt;Turns out, yes — minimum $5 deposit, around $0.03 per voice command. The 5-line rule wasn't just debugging discipline — it was a reminder that when building with AI, slowness is your ally. Also, apparently so is having a credit card.&lt;/p&gt;
&lt;h3&gt;
  
  
  🔁 The Loop (Or: Why Claude Needs Multiple Turns)
&lt;/h3&gt;

&lt;p&gt;When I said, “delete the red Welcome button,” Claude couldn’t just … do it in one go.&lt;/p&gt;

&lt;p&gt;From Claude’s point of view:&lt;br&gt;
1️⃣ Get the tree (get_tree)&lt;br&gt;
2️⃣ Find the red Welcome button&lt;br&gt;
3️⃣ Call delete_component with the right keys&lt;/p&gt;

&lt;p&gt;Problem: Claude can only use one tool per turn. Like a video game character who can only do one action before waiting for your input.&lt;/p&gt;

&lt;p&gt;Claude: "I have retrieved the tree."&lt;br&gt;
Me: "Great! Now delete the button."&lt;br&gt;
Claude: "I cannot. It is not my turn."&lt;br&gt;
Me: "...this is like playing chess with a very polite robot."&lt;br&gt;
Claude: "Check."&lt;/p&gt;



&lt;p&gt;Solution: build a loop so it can use a tool → see the result → think → use another.&lt;/p&gt;

&lt;p&gt;(One small while-loop for code, one giant leap for machine autonomy.)&lt;/p&gt;
&lt;h3&gt;
  
  
  🔥 The Chokidar + SSE Symphony
&lt;/h3&gt;

&lt;p&gt;At this point:&lt;/p&gt;

&lt;p&gt;✅ Voice commands working&lt;br&gt;
✅ Property updates working&lt;br&gt;
❌ UI still clueless&lt;/p&gt;

&lt;p&gt;Enter stage left: Chokidar, the watcher, and Server-Sent Events, the messenger.&lt;/p&gt;

&lt;p&gt;Chokidar just stares at component-tree.json like a very dedicated stalker. The moment it twitches — it screams in &lt;em&gt;binary&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;watcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&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="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SSE keeps an open line to the browser, ready to whisper: “Hey, something happened.”&lt;br&gt;
React refetches, the UI rerenders, and peace returns to the galaxy.&lt;/p&gt;
&lt;h3&gt;
  
  
  🎯 The Victory Lap
&lt;/h3&gt;

&lt;p&gt;THE APP WORKS.&lt;/p&gt;

&lt;p&gt;“Add a blue Welcome button.” → It appeared.&lt;br&gt;
“Make it pink.” → It blushed.&lt;br&gt;
“Delete the pink button.” → Gone.&lt;/p&gt;

&lt;p&gt;I definitely danced. The chair did a little spin.&lt;br&gt;
My cat watched from the couch, radiating judgment.&lt;br&gt;
She's seen me debug before. This changes nothing between us.&lt;/p&gt;

&lt;p&gt;All the moving pieces — voice input, MCP servers, Claude's orchestration, real-time updates — finally talking like old friends at a coffee shop.&lt;br&gt;
Me? Trying not to cry into my keyboard. (The keys stick when they get wet. Learned that the hard way.)&lt;/p&gt;

&lt;p&gt;🎬 Proof of Life: Here’s the app listening, obeying, and making me question the definition of "control."&lt;br&gt;


  &lt;iframe src="https://www.youtube.com/embed/qXeqTw3744k"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  🧩 The Stack (a.k.a. How the Magic Actually Works)
&lt;/h3&gt;

&lt;p&gt;Voice Input (Web Speech API)&lt;br&gt;
    ↓&lt;br&gt;
Next.js API (MCP Client)&lt;br&gt;
    ↓&lt;br&gt;
Anthropic Claude API&lt;br&gt;
    ↓&lt;br&gt;
component-tree-services (MCP Server)&lt;br&gt;
    ↓&lt;br&gt;
component-tree.json&lt;br&gt;
    ↓&lt;br&gt;
Chokidar (File Watcher)&lt;br&gt;
    ↓&lt;br&gt;
SSE (Real-time Updates)&lt;br&gt;
    ↓&lt;br&gt;
React (UI Re-render)&lt;/p&gt;

&lt;p&gt;A perfect loop — thoughts to words, words to code, code to UI — stitched together by caffeine and curiosity.&lt;/p&gt;

&lt;h3&gt;
  
  
  💭 What Just Happened Here?
&lt;/h3&gt;

&lt;p&gt;React Compiler saved my renders.&lt;br&gt;
Claude API saved my sanity.&lt;br&gt;
MCP saved the project.&lt;br&gt;
And the 5-line rule? That saved me.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚀 Next Up: Deploy Like It’s 2025
&lt;/h3&gt;

&lt;p&gt;Now that everything works — servers hum, Claude orchestrates, components obey — there’s only one thing left: set it free.&lt;/p&gt;

&lt;p&gt;In Part 4, I take this caffeine-fueled contraption to Vercel and see if the cloud is ready for an app that talks back.&lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;br&gt;
It’s live or nothing. ⚡️&lt;br&gt;
(Or as my laptop calls it: "may the fans be ever in your favor.")&lt;/p&gt;

&lt;p&gt;P.S. Repo is live: &lt;a href="https://github.com/sagi0312/SayBuild" rel="noopener noreferrer"&gt;SayBuild&lt;/a&gt;. You’ll need an Anthropic API key, a tolerance for experimental tech, and a cat for moral support. Cat optional but recommended.&lt;/p&gt;

&lt;p&gt;UPDATE (Oct 30, 2025):&lt;br&gt;
It's live at saybuild.vercel.app.&lt;br&gt;
Getting it there involved the usual Supabase/Vercel dance—Auth redirects pointing at localhost, environment variables playing hide-and-seek, and ESLint blocking deployment over my types. Not glamorous, but it finally is deployed!&lt;br&gt;
Also switched from Claude Sonnet to Haiku (30x cheaper, still excellent at function calling). Turns out you don't need the Ferrari when the Honda does the job just fine.&lt;br&gt;
Try it out. Break it. Let me know.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>nextjs</category>
      <category>anthropic</category>
    </item>
    <item>
      <title>React and the City ⚡️: Nevertheless, She Persisted</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Sat, 18 Oct 2025 02:06:41 +0000</pubDate>
      <link>https://dev.to/sagi0312/react-and-the-city-nevertheless-she-persisted-3n9a</link>
      <guid>https://dev.to/sagi0312/react-and-the-city-nevertheless-she-persisted-3n9a</guid>
      <description>&lt;p&gt;⚡️ Part 2: May the Force Be With You!&lt;/p&gt;

&lt;p&gt;FIELD NOTE: Continuing research on Project SayBuild, the voice-driven page builder.&lt;br&gt;
After React Compiler restored my faith in chivalry, I decided to flirt with English literature — language parsing. The results were… how shall I put it? Humbling.&lt;/p&gt;

&lt;p&gt;🔬 EXPERIMENT 2: Custom Pattern Matching for Voice Commands&lt;/p&gt;

&lt;p&gt;Objective:&lt;br&gt;
Teach the builder to understand speech without using an LLM.&lt;br&gt;
Why skip the obvious solution?&lt;br&gt;
Pride. Pure, unfounded pride.&lt;/p&gt;

&lt;p&gt;Hypothesis:&lt;br&gt;
If I can break every command into verbs, nouns, prepositions, and modifiers — then map them to CRUD operations on the component tree — I’ll have unearthed "intelligence" once again.&lt;/p&gt;

&lt;p&gt;Estimated time to success: 30 minutes. With beer breaks every 5.&lt;/p&gt;

&lt;p&gt;🧠 Day 1 — Confidence Level: 100%&lt;/p&gt;

&lt;p&gt;My parser is elegant. My pattern matching is flawless. &lt;br&gt;
I’m basically building natural language understanding from scratch. Future historians will bow before the great Anju.&lt;/p&gt;

&lt;p&gt;😵 Day 2 — Confidence Level: 12%&lt;/p&gt;

&lt;p&gt;Turns out humans don’t speak in clean patterns.&lt;br&gt;
They mumble. They change their minds mid-sentence. They say things like, "Add a big-ish button in the middle of that... uh... brownish thingy."&lt;br&gt;
Regex cried. I cried. We all cried.&lt;/p&gt;

&lt;p&gt;🪦 DAY 3 – 3:00 AM&lt;/p&gt;

&lt;p&gt;I surrender.&lt;br&gt;
Deleted half the code. Summoned the LLM like a desperate summoning ritual, ego served on a platter.&lt;br&gt;
It responded immediately.&lt;br&gt;
It understood "Add a big-ish button in the middle of the brownish thingy."&lt;br&gt;
It knew which component "it" referred to.&lt;br&gt;
It handled every edge case I'd spent three days regex-fighting.&lt;/p&gt;

&lt;p&gt;Time to implement: 45 minutes.&lt;/p&gt;

&lt;p&gt;☠️ Conclusion:&lt;br&gt;
Hubris detected.&lt;br&gt;
Pattern matching is strong with the Dark Side.&lt;br&gt;
LLM partnership initiated.&lt;/p&gt;

&lt;p&gt;🧩 THE DIY PARSER PHASE (RIP)&lt;br&gt;
The plan was simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verbs → CRUD operations (add, delete, update, move)&lt;/li&gt;
&lt;li&gt;Nouns → UI components (button, text, image)&lt;/li&gt;
&lt;li&gt;Prepositions → Spatial relationships (inside, below, next to)&lt;/li&gt;
&lt;li&gt;Modifiers → Props (big, blue, centered)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Linguistics 101, right? Just map words to actions.&lt;/p&gt;

&lt;p&gt;Suffice to say, it was &lt;em&gt;not&lt;/em&gt; Linguistics 101 😒&lt;/p&gt;

&lt;p&gt;The way the LLM handled pattern matching, you’d think it was built on that &lt;em&gt;very&lt;/em&gt; concept.&lt;/p&gt;

&lt;p&gt;But then it hit me — why stop at parsing?&lt;br&gt;
What if the LLM didn’t just understand the commands… what if it orchestrated everything?&lt;/p&gt;

&lt;p&gt;🧭 FIELD NOTE: The MCP Awakens&lt;/p&gt;

&lt;p&gt;For the past year, everyone’s been talking about MCP servers.&lt;br&gt;
Every conference. Every LinkedIn post. Every &lt;em&gt;"what’s new in AI"&lt;/em&gt; panel.&lt;br&gt;
I nodded along politely, secretly wondering, &lt;em&gt;"Is this another blockchain in the making?"&lt;/em&gt; 🤨&lt;/p&gt;

&lt;p&gt;Then I wandered into an MCP session at the Atlanta Developer Conference.&lt;br&gt;
Dimly lit room. Engineers leaning forward.&lt;br&gt;
The presenter described it simply: lightweight servers that let LLMs talk with structure, schema, and boundaries — clean delegation, clear contracts.&lt;/p&gt;

&lt;p&gt;Something clicked.&lt;br&gt;
I walked out of that room knowing exactly what I had to do.&lt;br&gt;
So I did what any reasonable developer would: went home, abandoned my laundry to its fate, and rewired SayBuild overnight.&lt;/p&gt;

&lt;p&gt;🧩 Curiosity killed the cat but satisfaction brought it back&lt;/p&gt;

&lt;p&gt;The Setup:&lt;/p&gt;

&lt;p&gt;2 MCP Servers:&lt;br&gt;
🧠 State Server — reads and writes to the component tree&lt;br&gt;
📊 Data Server — holds component-tree.json + Chokidar watcher&lt;/p&gt;

&lt;p&gt;Other players:&lt;br&gt;
1 LLM: the orchestrator — smart enough to delegate&lt;br&gt;
1 Next.js App: the display layer with live updates via SSE&lt;/p&gt;

&lt;p&gt;Converted the project to a pnpm workspace with proper package separation. Immediately pushed 123MB of node_modules to GitHub because /node_modules only ignores root — not workspace folders. &lt;/p&gt;

&lt;p&gt;Public Service Announcement for monorepo newbies: use node_modules (without '/') in order to ignore it everywhere. 🙇🏽‍♀️&lt;/p&gt;

&lt;p&gt;🧭 MCP Architecture&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%2F980r91l0ze3ygpf5ox5u.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%2F980r91l0ze3ygpf5ox5u.png" alt="MCP architecture" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next up: wiring it all together — two MCP servers, one LLM orchestrator, and a stubborn developer who just wouldn't quit. Stay tuned for Part 3: The Servers Strike Back.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devjournal</category>
      <category>mcp</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>☕ Unsolicited Wisdom from My Ceramic Life Coach</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Wed, 08 Oct 2025 03:36:23 +0000</pubDate>
      <link>https://dev.to/sagi0312/unsolicited-wisdom-from-my-ceramic-life-coach-1m04</link>
      <guid>https://dev.to/sagi0312/unsolicited-wisdom-from-my-ceramic-life-coach-1m04</guid>
      <description>&lt;p&gt;My mug said to me I should stop checking LinkedIn and start writing again. I told it to mind its own handle. &lt;br&gt;
The nerve!☕️&lt;/p&gt;

&lt;p&gt;So… My coffee mug and I have been in a committed relationship for 8 months now. &lt;/p&gt;

&lt;p&gt;We’ve been through all my ups and downs together — the late-night “Maybe I should just become a stripper… look at CardiB already!” spirals, the unfinished Leetcode medium dynamic programming problems, and my designer collection of rejection emails — you know, the 'we were truly impressed' ones sent from do-not-reply — stored in a PriorityQueue minHeap ranked by fake warmth.&lt;/p&gt;

&lt;p&gt;And it’s also my most annoying best friend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"You could practice Dijkstra’s algorithm."&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Me&lt;/strong&gt;: "Why? I’m not even sure I can find the shortest path to employment."&lt;/p&gt;

&lt;p&gt;She huffs a little.&lt;/p&gt;

&lt;p&gt;I open Leetcode. Stare at 'Two Sum' like it personally wronged me. Close it. She eyes me critically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: "Remember when I used to do this stuff for fun? Like, actual fun? I’d stay up till 3 a.m. debugging some stupid recursive function just because I enjoyed it. Now I’m supposed to invert a binary tree while maintaining eye contact and ‘showing my thought process.’ Ugh."&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"Suck it up, buttercup. Skeletons have more backbone — and they'd probably nail the system design round."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;She laughed at her own joke.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: "I hate you."&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"No you don't. I'm literally the only relationship that's working out for you right now."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I used to deploy to AWS. Now, I just stare at the clouds for 30 minutes and hope the universe autosaves my future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"You know what your problem is?"&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Me&lt;/strong&gt;: "Oh good, a list. I love lists."&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"Maybe you should follow up?"&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Me&lt;/strong&gt;: "With who? The recruiter who disappeared after asking for my availability, or the one who called me ‘Anjay’?"&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"Both. The living and the dead deserve closure."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I stare into what’s left of my coffee. It stares back — judgmentally, of course.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: "You think I’m wasting time, don’t you?"&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"You? The great Anju?"&lt;/em&gt; She scoffed at me.&lt;br&gt;
&lt;em&gt;"You’re just running an extended background process called existential dread."&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Me&lt;/strong&gt;: "Ha-ha."&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"Relax. Maybe this isn’t a gap. Maybe it’s a refactor."&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Me&lt;/strong&gt;: "You sound like one of those LinkedIn influencers who post 'Stop scrolling. Start building.' and then sell online courses."&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"Maybe you do need some discipline."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I roll my eyes, but something about it sticks.&lt;br&gt;
A refactor? Huh… &lt;br&gt;
All those old patterns I wrote under pressure (the ones those K-pop demon hunters warned me about) — all the unnecessary dependencies I kept around just to make things compile.&lt;br&gt;
Maybe they’re being rewritten quietly, in the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: "Okay, okay. I get it. You're very wise for a vessel."&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"I contain your caffeine. I am your life force. Show some respect."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I sigh, open my laptop, and hover over a blank document.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: "What now?" I ask.&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"Write."&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"Not a résumé. Something real."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"Finally. Was that so hard?"&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Me&lt;/strong&gt;: "Shut up. You're just a cup."&lt;br&gt;
&lt;strong&gt;Mug&lt;/strong&gt;: &lt;em&gt;"A cup that's been carrying you for eight months. You're welcome."&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>jobsearch</category>
      <category>career</category>
      <category>interview</category>
    </item>
    <item>
      <title>React and the City 💘: The Compiler Saves the Day</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Sat, 27 Sep 2025 01:57:03 +0000</pubDate>
      <link>https://dev.to/sagi0312/building-a-voice-driven-page-builder-part-1-how-react-compiler-solved-my-performance-crisis-3cpg</link>
      <guid>https://dev.to/sagi0312/building-a-voice-driven-page-builder-part-1-how-react-compiler-solved-my-performance-crisis-3cpg</guid>
      <description>&lt;p&gt;&lt;strong&gt;Welcome to the pilot episode of - React and the City&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And yes, it’s another AI chatbot tutorial &lt;br&gt;
(cue the collective groans reverberating across the internet and echoing into the galaxy far, far away🌌).&lt;/p&gt;

&lt;p&gt;But this one’s special. Why, you ask? Because you never forget your first. 😉&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;From Rejection to Experiment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Picture this: after months of interviews, the rejection landed like a guy who talks marriage, then ghosts the second you ask to see his house.&lt;/p&gt;

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

&lt;p&gt;Here’s the upside, though - the take-home assignment planted an idea. The task was to build a “mini” version of their visual page builder: the usual drag-and-drop editor hooked up to an iframe preview. Standard fare.&lt;/p&gt;

&lt;p&gt;Except while writing the jest tests, I couldn’t stop thinking about Cypress. You know how Cypress runs tests in a little Broadway show right in front of you? And then it hit me: what if building the page wasn’t about dragging or typing… but talking?&lt;/p&gt;

&lt;p&gt;Cue lightbulb moment. 💡&lt;br&gt;
 &lt;br&gt;
I won’t bore you with the standard page-builder setup (like one of those lazy “you look nice” compliments 🙃).&lt;br&gt;
It’s just the usual React component tree managing an iframe preview.&lt;br&gt;
If you’re curious, the repo’s here: &lt;a href="https://github.com/sagi0312/SayBuild" rel="noopener noreferrer"&gt;SayBuild&lt;/a&gt;.&lt;br&gt;
Let’s skip to the fun part: making it listen.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Making the Page Builder Listen&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I wanted to build something that would actually listen - a revolutionary concept in more than just tech 😉. Enter the Web Speech API. &lt;/p&gt;

&lt;p&gt;At first, everything seemed perfect. Speech recognition was working, my page builder was responding in real time.&lt;br&gt;
&lt;em&gt;I thought: this is the beginning of a beautiful friendship.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/kgerXd12qNI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Cool, right? Except my laptop started heating up like it was single-handedly handling every therapy session on ChatGPT across the country.&lt;/p&gt;

&lt;p&gt;Naturally, I assumed: “Oh no! Speech recognition is melting my CPU.” Alas — she had been such a lovely friend so far!&lt;/p&gt;

&lt;p&gt;Turns out… nope. 🙃&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Gaslighting Phase&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I was mourning my friendship with speech recognition… only to realize it was React gaslighting me all along.&lt;/p&gt;

&lt;p&gt;Debugging this felt like having &lt;em&gt;the talk&lt;/em&gt;. &lt;br&gt;
&lt;em&gt;Me&lt;/em&gt;: "Why are you re-rendering me constantly?"&lt;br&gt;
&lt;em&gt;React&lt;/em&gt;: "I don’t know… I just need space right now." &lt;/p&gt;

&lt;p&gt;What was actually frying my laptop? &lt;/p&gt;

&lt;p&gt;I opened the React Profiler, and there it was: my renders were spiraling out of control. Functions kept getting recreated, and my poor useEffect hook was spinning like a dog chasing its tail.🌀&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;sendMessageToHost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Message&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;iframeRef&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;contentWindow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;iframeRef&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;contentWindow&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="nx"&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;http://localhost:3000&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="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;sendMessageToHost&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MESSAGE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_COMPONENTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;debouncedComponentTree&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;debouncedComponentTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sendMessageToHost&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React and its mind games! Normally, you toss in a useCallback, hope ESLint nags you about missed dependencies, and move on.&lt;/p&gt;

&lt;p&gt;But this time I thought: &lt;em&gt;what if I let the new React Compiler do the heavy lifting - give the dude a chance?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;React Compiler to the Rescue&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I felt like I met Lisaan Al-Ghaib when I turned on the experimental compiler in next.config.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// next.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;reactCompiler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I deleted all my manual memoization. &lt;/p&gt;

&lt;p&gt;The results? Render times dropped from 20.8ms → 2.1ms. No useCallback, no headaches, no babysitting dependencies.&lt;/p&gt;

&lt;p&gt;Honestly, React Compiler felt like a knight in shining armor. 🛡️&lt;/p&gt;

&lt;p&gt;The compiler looked at my sendMessageToHost function, realized it had no dependencies, and just… memoized it for me.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Read Part 2: &lt;a href="https://dev.to/sagi0312/react-and-the-city-nevertheless-she-persisted-3n9a"&gt;⚡️Nevertheless, She Persisted&lt;/a&gt;&lt;/strong&gt; &lt;em&gt;(In which the builder learns to understand you - and promptly humbles me.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Future&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now I have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A page builder that listens (mind-blowing!).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Laptop no longer stranded in the Sahara without a water bottle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Daydreams of a future with the React Compiler. 💭&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next I focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Parsing commands like “add a button with text ‘Click Me’”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handling chaos like “make it blue” when there are five buttons&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mapping natural speech to component props without losing your mind&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically, we’re past the talking stage — things are getting serious. 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;"Thank U, Next" by Ariana Grande&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes the best ideas show up when life goes off script.&lt;/p&gt;

&lt;p&gt;This one just happens to involve speech recognition, a rejection email, and a little help from the React Compiler.&lt;/p&gt;

&lt;p&gt;🎤 To be continued… 💭&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>frontend</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Breaking the Rules at Privet Drive: A React Origin Story</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Tue, 23 Sep 2025 21:09:10 +0000</pubDate>
      <link>https://dev.to/sagi0312/react-and-the-philosophers-component-4dnk</link>
      <guid>https://dev.to/sagi0312/react-and-the-philosophers-component-4dnk</guid>
      <description>&lt;p&gt;The frontend developers of number 2013, Privet Drive, were proud to say they kept their code perfectly normal, thank you very much. HTML stayed in its cupboard, CSS in its closet, JavaScript in its corner — and they liked it that way. And here I was, breaking all their sacred rules.&lt;/p&gt;

&lt;p&gt;I was small and skinny for my age, and wore my cousin Angular's oversized hand-me-downs. My code looked clunky next to my bigger, successful cousin.&lt;/p&gt;

&lt;p&gt;One morning, on May 29th, 2013, a letter arrived — not by owl, but on a stage at JSConf US. It wasn’t sealed in wax, but in curiosity. Inside: JSX.&lt;/p&gt;

&lt;p&gt;That day Jordan Walke introduced me to the world; I wore my Sunday best to the conference and the programmers looked skeptical. Some even hostile. “JSX! Mixing HTML and JavaScript? An abomination,” they scoffed. Most of the world still bowed to the Dark Lord jQuery.&lt;/p&gt;

&lt;p&gt;Underneath my awkwardness, I had talent. My secret sauce -&amp;gt; always redraw the whole tree. &lt;/p&gt;

&lt;p&gt;Not literally - duh, I'm not a barbarian.&lt;/p&gt;

&lt;p&gt;To many developers, the DOM felt like a brick wall. I discovered a secret passage — a virtual DOM, hidden in plain sight — where updates could slip through. There, I could diff trees and apply only the changes: same type? patch props; different type? replace the node. &lt;/p&gt;

&lt;p&gt;At first, my children were shuffled about like nameless first-years on the train. But then I found the magic of a key. At last, each child was sorted not by seat, but by identity — like a Sorting Hat whispering who they truly were.&lt;/p&gt;

&lt;p&gt;Two years had passed by then. 2015 was a big year for me. I started embracing simple, elegant, stateless functional components - little functions that took props and returned JSX, nothing more. Little did I know I was planting the seeds of my own future, but I'm getting ahead of myself.&lt;/p&gt;

&lt;p&gt;By then, I was v0.14. One day at lunch, this kid came and sat next to me. "Hey, I'm JavaScript ES6+," he said casually. "That virtual DOM thing you do? Pretty impressive."&lt;/p&gt;

&lt;p&gt;Just like that, he became my best friend.&lt;/p&gt;

&lt;p&gt;TypeScript soon joined my circle too. The RFC process was my ancient headmaster: patient and wise. Each new spell of syntax or feature was weighed in his study before being released to the wider world.&lt;/p&gt;

&lt;p&gt;I also met Netflix and felt this overwhelming feeling of acceptance.&lt;/p&gt;

&lt;p&gt;I was still using my stack-based reconciliation back then. Start at the root, render each node, dive into the children — all the way down to the leaves before climbing back up. Recursive, synchronous, relentless. Since I was single-threaded, I froze the entire world until my work was done. It wasn’t elegance; it was brute determination.&lt;/p&gt;

&lt;p&gt;At first, I thought this was enough. But as I matured, I began to see the cracks: jank, dropped frames, unresponsive interfaces. My users noticed too — and it hurt. Somewhere deep inside, I felt the stirrings. The first whispers of what would eventually become Fiber.&lt;/p&gt;

&lt;p&gt;Cut to 2017. I completely rewrote my react internal engine to use fiber. Each React element had a corresponding fiber node and they are no longer re-created every render. &lt;/p&gt;

&lt;p&gt;I learned patience. I could split my work into chunks, pause midway, and resume later — or even abandon tasks I decided weren’t worth finishing.&lt;/p&gt;

&lt;p&gt;I began to live in two worlds at once: a current tree, the one you saw on the screen, and a work-in-progress tree, where I quietly shaped the next update. For the first time, I could prioritize my tasks — urgent updates first, background work later. This discipline opened the door to features I’d only dreamed of before: Concurrent Mode, Suspense, even hooks like useDeferredValue.&lt;/p&gt;

&lt;p&gt;At last, I had come of age!&lt;/p&gt;

&lt;p&gt;Before I knew it, it was 2018. And that's when I meet hooks! One look and I knew I was in love! Suddenly, everywhere I turned, it was useState, useEffect, useContext. They weren’t just utilities, they were a new mental model.&lt;/p&gt;

&lt;p&gt;Hooks transformed me. It felt like spring had finally arrived — and yes, roses had never smelled sweeter.&lt;/p&gt;

&lt;p&gt;With hooks, I found myself!&lt;/p&gt;

&lt;p&gt;My dear developers still loved me, but I could sense their growing frustration. The work of building UIs had become a balancing act: memoize too much and you choke performance, memoize too little and you drown in re-renders. useCallback, useMemo, React.memo — these spells cluttered their minds, stealing energy from the real joy of UI creation.&lt;/p&gt;

&lt;p&gt;I knew something had to change. For years, I had prided myself on my runtime capabilities — Fiber, scheduling, concurrency. But I had limits. I swallowed my pride and called in reinforcements.&lt;/p&gt;

&lt;p&gt;My brilliant, affluent uncle arrived — the React Compiler. He could see through my components, analyze them at build time, and slip optimizations in automatically. Where I once asked developers to carry the burden of performance, he promised to carry it for them.&lt;/p&gt;

&lt;p&gt;Looking back, I realize I may have outgrown my teenage infatuation with Hooks. Yet I haven’t left them behind — not fully. For now, they’re still by my side, shaping how I think and speak. And as I continue to evolve, I can see the React Compiler settling into something deeper as well - not just a distant uncle, but a father, a true part of my family.&lt;/p&gt;

&lt;p&gt;Soon it would be time for the next major release. &lt;br&gt;
"Will you write to me over the summer?" one developer asked as they pushed their latest commit.&lt;br&gt;
I smiled. They still didn't realize I was always there, always evolving.&lt;br&gt;
"I'll be around," I promised. "After all, someone has to keep breaking the rules at Privet Drive."&lt;/p&gt;

&lt;p&gt;For the first time in my life, I was truly excited to go home — because now I knew where I belonged: in the world of frontend development, making beautiful interfaces feel smooth, alive, and lightning fast.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Design Patterns by Purpose: The Command Pattern in Frontend Life (Part 4)</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Thu, 11 Sep 2025 14:03:09 +0000</pubDate>
      <link>https://dev.to/sagi0312/design-patterns-by-purpose-the-command-pattern-in-frontend-life-part-4-2f35</link>
      <guid>https://dev.to/sagi0312/design-patterns-by-purpose-the-command-pattern-in-frontend-life-part-4-2f35</guid>
      <description>&lt;h1&gt;
  
  
  The Command Pattern: Because Undo Shouldn't Be Rocket Science 🚀
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Undo Hell Nightmare
&lt;/h2&gt;

&lt;p&gt;Picture this: You're building a rich text editor. Users type, format, delete, paste images—and then inevitably smash Ctrl+Z expecting everything to magically reverse. Without the Command Pattern, you're staring into the abyss of "Undo Hell": a massive switch statement trying to track every possible action, or worse, attempting to reverse-engineer state changes like some kind of code archaeologist.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Been there? Yeah, we all have.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Command Pattern saves you from this nightmare. Instead of building an undo system, you build a time machine. Wrap every action in a command object, stack them up, and undo becomes as simple as popping items off a stack. Don't pray for perfect state tracking—queue commands and let them handle their own cleanup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Universal Remote Reality Check
&lt;/h2&gt;

&lt;p&gt;Let's start with something relatable. You've built the ultimate universal remote with three magic buttons—it can control anything! Naturally, you test it on your TV, your cat, and your spouse:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TV Remote&lt;/strong&gt; – Works like a dream. Press &lt;code&gt;TurnOn&lt;/code&gt; → TV lights up. Press &lt;code&gt;TurnOff&lt;/code&gt; → darkness. Press &lt;code&gt;ChangeChannel&lt;/code&gt; → new show appears. Finally, a receiver that actually receives commands! 📺&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cat Remote&lt;/strong&gt; – Pure chaos. Press &lt;code&gt;CuddleCommand&lt;/code&gt; → cat teleports to the opposite corner. Press &lt;code&gt;StopBeggingForFood&lt;/code&gt; → cat inhales the entire bowl, then screams like she's been starving for decades. Press &lt;code&gt;BehaveCommand&lt;/code&gt; → cat locks eyes with you and slowly pushes your coffee off the table. Classic. 😹&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spouse Remote&lt;/strong&gt; – Press &lt;code&gt;DoDishesCommand&lt;/code&gt;... radio silence. Press &lt;code&gt;ListenToMeCommand&lt;/code&gt;... still buffering. Press &lt;code&gt;FixFaucetCommand&lt;/code&gt;... you know how this ends. 😂&lt;/p&gt;

&lt;p&gt;Here's the beautiful part: same remote structure, completely different results. Each receiver interprets commands in their own way. The remote doesn't care if it's talking to a logical TV, a chaotic cat, or a mysteriously unresponsive spouse—it just fires the command and moves on.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That's Command Pattern in a nutshell: decouple the invoker from the receiver, wrap requests in neat packages, and let each receiver handle them however they see fit.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Friday Afternoon Panic
&lt;/h2&gt;

&lt;p&gt;Ever had your PM casually drop "Oh, can we add undo functionality?" on a Friday at 4 PM? If your code isn't already using Command Pattern, you're looking at a weekend of architectural surgery on a moving train.&lt;/p&gt;

&lt;p&gt;Here's the thing: adding undo to existing code is like trying to install airbags in a car that's already driving. With Command Pattern, undo is baked in from day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Command Pattern: The Code Reality
&lt;/h2&gt;

&lt;p&gt;Let's build this step by step, starting with the most cooperative receiver known to humankind: a light bulb. Unlike cats (or spouses), lights have exactly two states and always respond to commands.&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;// Command Interface - the contract for all commands&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ICommand&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;execute&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="nf"&gt;unexecute&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="c1"&gt;// The magic sauce for undo&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Receiver - the thing that actually does work&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Light&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;isOn&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;turnOn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isOn&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;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;Light is ON&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;turnOff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isOn&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;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;Light is OFF&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="c1"&gt;// Commands - actions wrapped in objects&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LightOnCommand&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ICommand&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Light&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;unexecute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turnOff&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Knows how to undo itself&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LightOffCommand&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ICommand&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Light&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turnOff&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;unexecute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Every command is its own time machine&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Invoker - your remote control&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RemoteControl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;undoStack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ICommand&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="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;redoStack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ICommand&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="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ICommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;off&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ICommand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;pressOn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;undoStack&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redoStack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Clear redo when new action happens&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;pressOff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;off&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;undoStack&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;off&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redoStack&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="nf"&gt;pressUndo&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;undoStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;undoStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&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="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unexecute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Command knows how to undo itself&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redoStack&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;command&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="nf"&gt;pressRedo&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redoStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redoStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&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="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;undoStack&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;command&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="c1"&gt;// Usage - simple and clean&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;light&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;Light&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;onCommand&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;LightOnCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;light&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;offCommand&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;LightOffCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;light&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;remote&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;RemoteControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;offCommand&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pressOn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    &lt;span class="c1"&gt;// Light is ON&lt;/span&gt;
&lt;span class="nx"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pressOff&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// Light is OFF  &lt;/span&gt;
&lt;span class="nx"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pressUndo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Light is ON (undid the off command)&lt;/span&gt;
&lt;span class="nx"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pressRedo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Light is OFF (redid the off command)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Notice how the remote doesn't know anything about lights—it just executes commands. That's the magic of decoupling.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend Reality: Where You've Seen This Before
&lt;/h2&gt;

&lt;p&gt;Command Pattern isn't some academic exercise—you interact with it daily:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Docs undo&lt;/strong&gt; - Every keystroke is a command&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Figma/Canva operations&lt;/strong&gt; - Drawing, moving, styling—all commands&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code&lt;/strong&gt; - Every edit, format, refactor is wrapped as a command&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Photo editors&lt;/strong&gt; - Crop, filter, adjust—each step is undoable because it's a command&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any app with Ctrl+Z&lt;/strong&gt; - If it has undo, it probably uses Command Pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anywhere you see "Edit → Undo" in a menu, someone implemented Command Pattern (or should have).&lt;/p&gt;

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

&lt;p&gt;Here's where Command Pattern becomes your secret weapon. Imagine a single Undo button you can drop anywhere in your React app—toaster notifications, modals, WYSIWYG editors. Same button, completely different behaviors.&lt;/p&gt;

&lt;p&gt;The button doesn't know what it's undoing. Each context provides its own command:&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;// Command interface&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UndoCommand&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;execute&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Universal Undo Button - works anywhere&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UndoButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UndoCommand&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="err"&gt;↶&lt;/span&gt; &lt;span class="nx"&gt;Undo&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Different commands for different contexts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toasterUndo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UndoCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;execute&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;showDeletedItemAgain&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;modalUndo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UndoCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;execute&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;reopenModal&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;editorUndo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UndoCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;execute&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;undoLastTextOperation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Same button, different superpowers&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ToastNotification&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UndoButton&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toasterUndo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ToastNotification&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Modal&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UndoButton&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;modalUndo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Modal&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TextEditor&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UndoButton&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;editorUndo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/TextEditor&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;One button to rule them all. The Command Pattern makes your components truly reusable.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Management: The Harsh Reality
&lt;/h2&gt;

&lt;p&gt;Here's what the tutorials don't tell you: Command Pattern can eat your RAM for breakfast. Every undoable action lives in memory until you clear it. I learned this the hard way when users crashed our app by typing a novel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production-ready strategies:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cap your undo stack&lt;/strong&gt; (50-100 commands max)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch tiny operations&lt;/strong&gt; (merge keystrokes into word-level commands)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compress repetitive actions&lt;/strong&gt; (10 cursor movements → 1 "move right 10" command)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear on major operations&lt;/strong&gt; (file save, page navigation)
&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SmartRemoteControl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;undoStack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ICommand&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="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;MAX_UNDO_HISTORY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ICommand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;undoStack&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;command&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Prevent memory leaks&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;undoStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_UNDO_HISTORY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;undoStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Goodbye, oldest command&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;
  
  
  Advanced Patterns: Level Up Your Game
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Macro Commands&lt;/strong&gt; - Group operations into super-commands:&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;// "Format Paragraph" = Select All + Bold + Center Align&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formatParagraph&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;MacroCommand&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;SelectAllCommand&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;BoldCommand&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;AlignCenterCommand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// One undo reverses all three operations&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Command Chaining&lt;/strong&gt; - Build pipelines that auto-rollback on failure:&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;// Form submission pipeline&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CommandPipeline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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;ValidateFormCommand&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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;SaveDraftCommand&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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;SubmitToAPICommand&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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;ShowSuccessCommand&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeWithRollback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// If any step fails, previous steps auto-undo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When NOT to Use Command Pattern
&lt;/h2&gt;

&lt;p&gt;Don't be that developer who turns everything into a command. Skip it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple toggles&lt;/strong&gt; (&lt;code&gt;isDark ? 'dark' : 'light'&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-off actions&lt;/strong&gt; that will never need undo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance-critical paths&lt;/strong&gt; (command dispatch has overhead)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic CRUD&lt;/strong&gt; where you're just calling a method&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're creating commands just to call a single method with no undo needs, you're overthinking it. Not every button press needs to be a command.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Command Pattern turns chaos into order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Invokers&lt;/strong&gt; (buttons, remotes) don't need to know what they control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commands&lt;/strong&gt; wrap requests and handle their own undo logic
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Receivers&lt;/strong&gt; do the actual work without knowing who called them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You&lt;/strong&gt; get undo/redo for free, plus amazing flexibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's the programming equivalent of having a universal remote that actually works. Your future self will thank you when requirements change next sprint (and they always do).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What's your Command Pattern war story? Drop it in the comments—we've all been there.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>designpatterns</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Design Patterns by Purpose: The Strategy Pattern in Frontend Life (Part 3)</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Fri, 22 Aug 2025 02:46:04 +0000</pubDate>
      <link>https://dev.to/sagi0312/design-patterns-by-purpose-the-strategy-pattern-in-frontend-life-part-3-55i4</link>
      <guid>https://dev.to/sagi0312/design-patterns-by-purpose-the-strategy-pattern-in-frontend-life-part-3-55i4</guid>
      <description>&lt;p&gt;You've tamed structure (Module) and domesticated creation (Factory). Next up: behavior.&lt;/p&gt;

&lt;p&gt;Consider a payment processor that needs different personalities (credit card, PayPal, crypto, bank transfer, gift card). Left alone, it turns into an if/else hydra. The Strategy Pattern trims that chaos: you define a small, stable interface for the operation (say process, validate, or charge) and pass in interchangeable implementations at runtime. Call sites stay consistent; only the strategy changes. Result: fewer branches, cleaner tests, and new variants without touching the core. Swap, don't sprawl.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cat Behaviors: The Furry Problem
&lt;/h2&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%2F4zasrsu2esekaswxjbpj.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%2F4zasrsu2esekaswxjbpj.png" alt="trategy Pattern UML — BaseCat with StreetCat, HouseCat (necktie), Maneki-neko, and RoboCat. Behaviors via Eat/Sound/Move strategies." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Meet Cat, our base class.&lt;br&gt;
Now the variants: StreetCat, HouseCat, ManekiNeko, HelloKitty (famously… silent).&lt;/p&gt;

&lt;p&gt;Hard-coding eat(), meow(), and move() into Cat breaks half the family—some behave differently, some don’t meow at all. Copy-pasting those methods into every subclass? Hairball city.&lt;/p&gt;

&lt;p&gt;Enter Strategy: pull -&amp;gt; eat, sound, and move into small, swappable objects with the same interface. Compose each cat with the behaviors it actually needs at runtime. New cat? Meet RoboCat—USB-C-powered, doesn’t eat, outputs a synthetic meow, and yes, it flies. You just plug in eatBehavior: none, soundBehavior: synth, and moveBehavior: thrusters. No base-class surgery, no if/else hairballs—just composition that feels like a firmware upgrade.&lt;/p&gt;
&lt;h2&gt;
  
  
  A real-world pass: CollapsiblePanel with pluggable behaviors
&lt;/h2&gt;

&lt;p&gt;Time to leave the cat café and touch UI. The panel’s structure stays boring on purpose; the behavior gets swapped in.&lt;/p&gt;

&lt;p&gt;You ship a solid CollapsiblePanel, and suddenly it’s everywhere. Marketing wants color + sparkle on click. Settings wants non-clickable panels. The dashboard wants panels sorted by priority. Sound familiar? This is where the Strategy Pattern earns its keep: don’t fork your component or stuff it with if/else. Make it behavior-agnostic and accept tiny “strategies” for clicks, sorting—whatever you need.&lt;/p&gt;

&lt;p&gt;Think of it this way: the panel is the car; strategies are the drivers. The car exposes the wheel and pedals; the driver decides how to drive. Your panel exposes markup and state; strategies decide what to do.&lt;/p&gt;

&lt;p&gt;You can create small strategy functions for different behaviors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Strategy objects&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clickStrategies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;colorSparkle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;addSparkleEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="na"&gt;getStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightblue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all 0.3s&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;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;onClick&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="c1"&gt;// No-op&lt;/span&gt;
   &lt;span class="na"&gt;getStyle&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="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pointerEvents&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="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;sortStrategies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panels&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;panels&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;alphabetical&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panels&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;panels&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;localeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="c1"&gt;// The panel stays behavior-agnostic&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CollapsiblePanel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clickStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clickStrategies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; 
       &lt;span class="nx"&gt;onClick&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="nx"&gt;clickStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
       &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;clickStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
       &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;panel-header&lt;/span&gt;&lt;span class="dl"&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;title&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&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;panel-content&lt;/span&gt;&lt;span class="dl"&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;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&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CollapsiblePanel&lt;/span&gt; 
 &lt;span class="nx"&gt;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;marketing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
 &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Campaign Results&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="nx"&gt;clickStrategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;clickStrategies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorSparkle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CollapsiblePanel&lt;/span&gt; 
 &lt;span class="nx"&gt;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;dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Web Traffic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="nx"&gt;clickStrategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;clickStrategies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Before You If/Else
&lt;/h2&gt;

&lt;p&gt;When you feel an if (type === 'special') coming on, pause. Ask: “Could this be a strategy instead?” If yes, extract a tiny function, pass it in, and keep your component calm. Future-you (and your team) will thank you when requirements change again next sprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;p&gt;No default strategy? Give your component a safe fallback (e.g., disabled behavior) so it never crashes when someone forgets to pass one in.&lt;/p&gt;

&lt;p&gt;Testing panic? Don’t test every combo :)&lt;/p&gt;

&lt;p&gt;Over-strategizing? Not every if deserves a strategy. A quick inline check is fine when there are only one or two cases and they won’t grow - extract them when you actually need the third variation.&lt;/p&gt;

&lt;h2&gt;
  
  
  When NOT to use Strategy:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Simple toggles (theme.dark ? 'dark' : 'light')&lt;/li&gt;
&lt;li&gt;One-off customizations that won't grow&lt;/li&gt;
&lt;li&gt;Performance-critical paths (strategy dispatch has overhead)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When Strategy shines:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multiple implementations of the same interface&lt;/li&gt;
&lt;li&gt;Runtime behavior switching&lt;/li&gt;
&lt;li&gt;Plugin architectures&lt;/li&gt;
&lt;li&gt;Algorithm families that need to be swappable&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Strategy is the gateway drug to plugin architectures. Mastering this helps you build micro-frontends, extensible design systems, and even frameworks that don't lock you into their opinions. Your components become platforms, not just UI blocks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Posting in case it helps someone.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>designpatterns</category>
      <category>refactoring</category>
      <category>react</category>
    </item>
    <item>
      <title>Design Patterns by Purpose: The Factory Pattern in Frontend Life (Part 2)</title>
      <dc:creator>Anju Karanji</dc:creator>
      <pubDate>Thu, 31 Jul 2025 22:32:22 +0000</pubDate>
      <link>https://dev.to/sagi0312/design-patterns-by-purpose-reuse-part-2-3500</link>
      <guid>https://dev.to/sagi0312/design-patterns-by-purpose-reuse-part-2-3500</guid>
      <description>&lt;h2&gt;
  
  
  🏭 The Factory Pattern – Creating Without Clutter
&lt;/h2&gt;

&lt;p&gt;Before I open a PR, I scan my code like a typical disappointed Asian parent: "Why are there three identical button setups? Who copy-pasted this API client everywhere? And what's with all these validators doing the exact same dance?"&lt;/p&gt;

&lt;p&gt;Each one technically works, but asking every file to memorize a 15-step recipe is like teaching the whole family to make rasam from scratch every time — someone’s bound to mess up the masalas.&lt;/p&gt;

&lt;p&gt;That’s where the Factory Pattern comes in: it centralizes creation.&lt;br&gt;
Instead of copy-pasting setup code, you just ask by intent — “primary button,” “authenticated client,” “email validator.” The factory knows the house recipe and returns a ready-to-use object.&lt;/p&gt;

&lt;p&gt;Best part: when you decide to switch from chat masala to turmeric (or swap an API provider), you update the factory once. Every dish — and every file — automatically gets the upgrade, no family meeting required.&lt;/p&gt;


&lt;h3&gt;
  
  
  Where the Factory Pattern Quietly Does Its Magic
&lt;/h3&gt;

&lt;p&gt;Think about visual page builders.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Component Factory for page builder&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ComponentFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&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;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HeroComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hero-section&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;defaultHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;500px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testimonial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TestimonialComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;showAvatar&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="na"&gt;maxLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unknown component type: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="c1"&gt;// Usage - clean and simple&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ComponentFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'Welcome' });&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s flexible, too. These factories are often built using &lt;strong&gt;polymorphism&lt;/strong&gt;, so if your current setup ever starts to feel clunky — or you need something more scalable — you can swap in a different factory without touching the rest of the system.&lt;br&gt;&lt;br&gt;
That kind of design stays clean for years.&lt;/p&gt;
&lt;h3&gt;
  
  
  Beyond the Basics: Simple, Method, and Abstract
&lt;/h3&gt;

&lt;p&gt;Do you see where I’m going with this?&lt;br&gt;
Imagine you have an Outfit Generator for different kinds of days:&lt;/p&gt;

&lt;p&gt;🧰 &lt;strong&gt;Simple Factory – kinda simplistic&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Simple Factory is a convenient helper that builds an object based on a parameter — like our Outfit Generator picking “pajamas” or “blouse &amp;amp; skirt.”&lt;/p&gt;

&lt;p&gt;⚠️ &lt;em&gt;Note: Purists don’t list this as an official “Gang of Four” pattern because it doesn’t involve inheritance or polymorphism — it’s basically a neat wrapper around new. Still, for small apps it’s practical and keeps creation logic in one spot.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OutfitFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wfh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mismatched pajama set&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;office&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Clean blouse &amp;amp; skirt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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;Unknown vibe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🏭 &lt;strong&gt;Factory Method – stylists with their own rules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Factory Method pattern delegates creation to specialized “stylists.”&lt;br&gt;
Each subclass knows how to assemble its look.&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;class&lt;/span&gt; &lt;span class="nc"&gt;Stylist&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;createOutfit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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;Override me&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WFHStylist&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Stylist&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;createOutfit&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pajamas + messy bun + cookie crumbs&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OfficeStylist&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Stylist&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;createOutfit&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Blouse, skirt, neat hair, hint of perfume&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Use this when different environments need their own construction steps but you want one interface: stylist.createOutfit()&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;strong&gt;Abstract Factory – complete lifestyle bundles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Abstract Factory builds families of related objects, keeping them consistent.&lt;br&gt;
Think of it as a recipe for the whole vibe:&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;class&lt;/span&gt; &lt;span class="nc"&gt;WFHBundleFactory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;createClothes&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comfy PJs&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;createHair&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Messy bun&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;createExtras&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Crumbs on top&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OfficeBundleFactory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;createClothes&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pressed blouse &amp;amp; skirt&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;createHair&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Freshly washed&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;createExtras&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Light perfume&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Perfect when you need coordinated sets — outfit, grooming, accessories — all matching the environment.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🧪 Testing &amp;amp; Single Responsibility (Tiny but Mighty)
&lt;/h3&gt;

&lt;p&gt;Factories also shine when it comes to unit testing and Single Responsibility.&lt;br&gt;
By moving setup code into one spot, your classes stay focused on behavior — and tests can inject mocks without wading through construction logic.&lt;br&gt;
(In outfit terms: you test how you wear the clothes, not how the wardrobe picked them.)&lt;/p&gt;


&lt;h3&gt;
  
  
  A Real-World Moment
&lt;/h3&gt;

&lt;p&gt;Here’s one example from a past project:&lt;/p&gt;

&lt;p&gt;I didn’t write the drag-and-drop code myself — but I remember noticing it.&lt;/p&gt;

&lt;p&gt;It worked fine in Chrome, but in Firefox, things got a little weird. At the time, most users were on Chrome, so the issues went unnoticed for a while. But when the team finally needed to fix it, they had a choice: scatter browser-specific &lt;code&gt;if-else&lt;/code&gt; checks throughout the code… or find a cleaner solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Before Factory - browser checks scattered everywhere&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleDragStart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Firefox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;effectAllowed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;move&lt;/span&gt;&lt;span class="dl"&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;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&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="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chrome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;effectAllowed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copyMove&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;// This logic gets duplicated in every drag handler...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// After Factory - clean separation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DragHandlerFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;create&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Firefox&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FirefoxDragHandler&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="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chrome&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ChromeDragHandler&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;DefaultDragHandler&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;class&lt;/span&gt; &lt;span class="nc"&gt;FirefoxDragHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;handleDragStart&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="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;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;effectAllowed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;move&lt;/span&gt;&lt;span class="dl"&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;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChromeDragHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;handleDragStart&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="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;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;effectAllowed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copyMove&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="c1"&gt;// Usage - no browser detection needed&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dragHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DragHandlerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;dragHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleDragStart&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main drag-and-drop code stayed clean. Easy to test. Easy to grow. When Safari needed support later, they just added another handler class — no rewrites, no mess scattered throughout the codebase.&lt;/p&gt;




&lt;h3&gt;
  
  
  When to Use (and Not Use) Factory Pattern
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Factory shines when you have:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple variations of similar objects that need different configurations&lt;/li&gt;
&lt;li&gt;Complex setup logic that you don't want scattered everywhere&lt;/li&gt;
&lt;li&gt;Objects that need environment-specific behavior (dev vs prod, mobile vs desktop)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Worth using Factory - multiple complex configurations&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;APIClientFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&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;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;debug&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="na"&gt;retries&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.company.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&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="s1"&gt;X-Environment&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;prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&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;p&gt;&lt;em&gt;Skip Factory when:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You only have one or two simple variations&lt;/li&gt;
&lt;li&gt;The setup is straightforward and unlikely to change&lt;/li&gt;
&lt;li&gt;You're just avoiding a few lines of code
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Overkill - simple toggle doesn't need Factory&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&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;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This is fine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rule of three: once you’ve set up the same complex object three times, it’s factory time.&lt;/p&gt;

&lt;p&gt;Scaling bonus: factories grow sideways, not everywhere.&lt;br&gt;
Need a new API environment? Add a case to the factory — the rest of the codebase stays blissfully unaware.&lt;br&gt;
Compare that to scattered if-else blocks you'd have to hunt down in dozens of files.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>designpatterns</category>
    </item>
  </channel>
</rss>
