<?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: Werliton Silva</title>
    <description>The latest articles on DEV Community by Werliton Silva (@werliton).</description>
    <link>https://dev.to/werliton</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%2F450483%2Feb166a12-3bfa-487f-aebd-a91d7c33a48a.png</url>
      <title>DEV Community: Werliton Silva</title>
      <link>https://dev.to/werliton</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/werliton"/>
    <language>en</language>
    <item>
      <title>Why Your React App Feels Slow (Hint: It’s Your Apollo Cache Strategy)</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Mon, 09 Feb 2026 18:55:48 +0000</pubDate>
      <link>https://dev.to/werliton/why-your-react-app-feels-slow-hint-its-your-apollo-cache-strategy-28b3</link>
      <guid>https://dev.to/werliton/why-your-react-app-feels-slow-hint-its-your-apollo-cache-strategy-28b3</guid>
      <description>&lt;p&gt;Hey dev! If you’ve ever felt the frustration of watching a component "flicker" white or take precious seconds to load info the user has already seen, you know that state management is no joke.&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%2Fx7fty8znkk40f1hat0om.gif" 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%2Fx7fty8znkk40f1hat0om.gif" alt="slow" width="236" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine you're building a financial dashboard. The user clicks on their profile, goes back home, checks settings... If every single click triggers a full request to the server, you're not just burning processing power - you're delivering a clunky experience. This is exactly why Apollo Client wasn't just born as a "fetcher," but as a powerful caching engine.&lt;/p&gt;

&lt;p&gt;Today, we’re getting straight to the point: mastering Apollo Fetch Policies so you can decide exactly when to hit the cache and when to knock on the server’s door.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Heart of Performance: Apollo's Cache
&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%2Fcm1olgurpgtrnbzk6ypo.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%2Fcm1olgurpgtrnbzk6ypo.png" alt="apollo" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apollo Client &lt;strong&gt;doesn't just fetch data&lt;/strong&gt;; it &lt;code&gt;normalizes and stores it&lt;/code&gt;. When you run a query, Apollo creates a local map. If you request that same data again, Apollo decides - based on your configuration - whether to go to the network or hand over what it already has instantly.&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%2Fcz3xz2noej13objbatab.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%2Fcz3xz2noej13objbatab.png" alt="arch" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. cache-first (The Smart Default)
&lt;/h3&gt;

&lt;p&gt;This is the default policy. Apollo looks at the cache: "Do I have this?" If yes, it returns it and never touches the network. If no, it fetches from the server and saves it for next time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: Product category lists that rarely change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical Example&lt;/strong&gt;:
&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;// Perfect for a list of tags the user already loaded when opening the app&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_CATEGORIES&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fetchPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cache-first&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. network-only (Maximum Consistency)
&lt;/h3&gt;

&lt;p&gt;Here, the &lt;code&gt;cache is ignored for reading&lt;/code&gt;. Apollo always hits the server for the &lt;strong&gt;latest version&lt;/strong&gt;. Note: It still saves the result to the cache for future queries using cache-first.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: Bank balances or real-time transaction statuses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical Example&lt;/strong&gt;:
&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;// Ensures the user sees the updated balance immediately after a transfer&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_USER_BALANCE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fetchPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;network-only&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. cache-only (Offline/Instant Mode)
&lt;/h3&gt;

&lt;p&gt;In this policy, Apollo will never &lt;code&gt;make a network request&lt;/code&gt;. If the data isn't in the cache, &lt;strong&gt;it returns an error or undefined&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: Secondary components that depend on data already loaded by a "parent" or the Home screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical Example&lt;/strong&gt;:
&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;// Displaying a username in a sidebar, assuming the login process already loaded this&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_USER_BASIC_INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fetchPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cache-only&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. no-cache (Privacy &amp;amp; Ephemerality)
&lt;/h3&gt;

&lt;p&gt;Similar to network-only, it &lt;code&gt;always goes to the server&lt;/code&gt;. The big difference? It doesn't store the result. The data disappears as soon as the &lt;strong&gt;component unmounts&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: Sensitive compliance data (GDPR) or temporary logs that shouldn't persist in memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical Example&lt;/strong&gt;:
&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;// Fetching audit logs that you don't want floating around in browser memory&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_SENSITIVE_LOGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fetchPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Policy&lt;/th&gt;
&lt;th&gt;Data Source&lt;/th&gt;
&lt;th&gt;Saves to Cache?&lt;/th&gt;
&lt;th&gt;Primary Goal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;cache-first&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cache (or Network if empty)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Loading Speed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;network-only&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always Network&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Data Consistency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;cache-only&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always Cache&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Zero Latency / Offline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;no-cache&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always Network&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Security &amp;amp; Memory Savings&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;Setting the right &lt;code&gt;fetchPolicy&lt;/code&gt; is what separates an amateur React app from a high-performance professional one. There is no single "best" policy - only the right policy for your user's specific flow. &lt;strong&gt;Balancing server load with cache speed is the secret to a fluid UX&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Did you find this technical tip helpful&lt;/strong&gt;? If you want to see how to configure next-fetch-policy to handle background updates while showing cached data, drop a comment below!&lt;/p&gt;




&lt;p&gt;Have you ever struggled with "stale data" using the default cache? Let me know how you handled it!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>Hands-on: Building Your Monorepo with Lerna and Yarn Workspaces</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Fri, 09 Jan 2026 14:59:00 +0000</pubDate>
      <link>https://dev.to/werliton/hands-on-building-your-monorepo-with-lerna-and-yarn-workspaces-1eii</link>
      <guid>https://dev.to/werliton/hands-on-building-your-monorepo-with-lerna-and-yarn-workspaces-1eii</guid>
      <description>&lt;p&gt;If you're tired of jumping from repository to repository just to update a single shared function, this guide is for you. Today, we're going to build a robust &lt;strong&gt;Monorepo&lt;/strong&gt; foundation using the power of &lt;strong&gt;Lerna&lt;/strong&gt; and the efficiency of &lt;strong&gt;Yarn Workspaces&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this duo unbeatable? 🤝
&lt;/h2&gt;

&lt;p&gt;Before we dive into the code, let's look at the "why":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Yarn Workspaces:&lt;/strong&gt; Handles the heavy lifting of dependencies. It prevents duplication and ensures your internal packages communicate seamlessly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lerna:&lt;/strong&gt; Acts as the conductor. It makes it easy to run commands in bulk (like running tests across 10 packages at once) and manages versioning for publishing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step-by-Step: From Zero to Monorepo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Preparing the Ground
&lt;/h3&gt;

&lt;p&gt;Create your project folder and initialize Git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-monorepo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-monorepo
git init
yarn init &lt;span class="nt"&gt;-y&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Activating Yarn Workspaces
&lt;/h3&gt;

&lt;p&gt;Open your &lt;code&gt;package.json&lt;/code&gt; and add the lines below. This is crucial to tell Yarn where your sub-projects will live:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-monorepo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"private"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workspaces"&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="s2"&gt;"packages/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We set &lt;code&gt;"private": true&lt;/code&gt; because the root repository itself should not be published to NPM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Initializing Lerna
&lt;/h3&gt;

&lt;p&gt;With Yarn ready, let's bring in Lerna to manage the workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; lerna
lerna init

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

&lt;/div&gt;



&lt;p&gt;This will create a &lt;code&gt;lerna.json&lt;/code&gt; file---the brain of our orchestration.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Creating Your First Packages
&lt;/h3&gt;

&lt;p&gt;Let's set up a structure with two example packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages
&lt;span class="nb"&gt;mkdir &lt;/span&gt;packages/api packages/web-app

&lt;span class="c"&gt;# Initializing each one&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;packages/api &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ../web-app &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn init &lt;span class="nt"&gt;-y&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Managing Dependencies Like a Pro 🚀
&lt;/h2&gt;

&lt;p&gt;This is where the magic happens. With &lt;strong&gt;Yarn Workspaces&lt;/strong&gt;, you don't need to enter each folder to install something.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Common Dependency (across all packages):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add lodash &lt;span class="nt"&gt;-W&lt;/span&gt;

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

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Specific Dependency (only for one package):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Adding React only to the web-app&lt;/span&gt;
workspace web-app yarn add react

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

&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Power of Single Commands with Lerna
&lt;/h2&gt;

&lt;p&gt;Imagine you have 5 packages, and all of them have a &lt;code&gt;test&lt;/code&gt; script in their &lt;code&gt;package.json&lt;/code&gt;. Instead of running them one by one, simply use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lerna run &lt;span class="nb"&gt;test&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Lerna will traverse every folder inside &lt;code&gt;packages/&lt;/code&gt; and execute the test in each one. Pure productivity!&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Best Practices to Keep You on Track
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Organization is Everything:&lt;/strong&gt; Keep naming clear. For example: &lt;code&gt;@my-project/ui&lt;/code&gt;, &lt;code&gt;@my-project/utils&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Document the Root:&lt;/strong&gt; Maintain a &lt;code&gt;README.md&lt;/code&gt; in the root explaining how to run the entire project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Set up a CI (like GitHub Actions) to run &lt;code&gt;lerna run build&lt;/code&gt; whenever a new Pull Request is opened.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;Setting up a monorepo with &lt;strong&gt;Lerna + Yarn Workspaces&lt;/strong&gt; is the first step toward scaling software engineering projects with quality. You gain consistency, reuse code efficiently, and stop fighting package management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Want to dive deeper?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://lerna.js.org/" rel="noopener noreferrer"&gt;Lerna Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://classic.yarnpkg.com/en/docs/workspaces/" rel="noopener noreferrer"&gt;Yarn Workspaces Guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Did you find this tutorial helpful? Do you have any questions about the setup? Let's talk in the comments below! 👇&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>javascript</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Monorepo Demystified: Turborepo vs. Lerna vs. Nx - Which one should you choose? 🚀</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Thu, 08 Jan 2026 14:37:51 +0000</pubDate>
      <link>https://dev.to/werliton/monorepo-demystified-turborepo-vs-lerna-vs-nx-which-one-should-you-choose-3aeh</link>
      <guid>https://dev.to/werliton/monorepo-demystified-turborepo-vs-lerna-vs-nx-which-one-should-you-choose-3aeh</guid>
      <description>&lt;p&gt;Have you ever felt like you're fighting a losing battle trying to keep libraries synced across multiple different repositories? If the answer is yes, you need to talk about &lt;strong&gt;Monorepos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we’ll demystify this concept and compare the 3 tools that dominate the market: &lt;strong&gt;Turborepo, Lerna, and Nx&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a Monorepo, anyway? 🤔
&lt;/h2&gt;

&lt;p&gt;Unlike the traditional &lt;em&gt;multirepo&lt;/em&gt; approach (one repository for each project), a &lt;strong&gt;Monorepo&lt;/strong&gt; is a single repository that houses multiple packages or applications. &lt;/p&gt;

&lt;p&gt;Imagine having your Frontend, Backend, and shared UI component library all living in one place, yet perfectly organized. The main benefits are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seamless Code Sharing:&lt;/strong&gt; Say goodbye to &lt;code&gt;npm publish&lt;/code&gt; every time you update an internal component.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total Consistency:&lt;/strong&gt; A single version of dependencies (like React or Jest) across all projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fluid Collaboration:&lt;/strong&gt; Changes affecting multiple systems can be made in a single Pull Request.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Comparison: The 3 Management Giants
&lt;/h2&gt;

&lt;p&gt;Managing a monorepo "by hand" is nearly impossible. This is where orchestration tools come in. Let’s break them down:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Turborepo (The Formula 1) 🏎️
&lt;/h3&gt;

&lt;p&gt;Focused on extreme speed. If you’re looking for performance without the headache, Turbo is the way to go.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key Advantage:&lt;/strong&gt; Features an &lt;strong&gt;intelligent caching system&lt;/strong&gt; (both local and remote). If the code hasn't changed, it won't recompile. Simple as that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ideal for:&lt;/strong&gt; Projects that prioritize simplicity and ultra-fast build times.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get started now&lt;/span&gt;
npx create-turbo@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Lerna (The Classic) 📚
&lt;/h3&gt;

&lt;p&gt;The tool that popularized the concept. It is robust, flexible, and extremely well-known within the community.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Advantage:&lt;/strong&gt; A massive community. If you run into an error, someone has likely already solved it on Stack Overflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ideal for:&lt;/strong&gt; Projects that need highly customized package publishing and versioning workflows.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Get started now
npm install --global lerna
lerna init

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Nx (The Swiss Army Knife) 🛠️
&lt;/h3&gt;

&lt;p&gt;Nx isn't just a build tool; it's a full-blown development platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Advantage:&lt;/strong&gt; Extreme modularity and flawless native support for Angular, React, and Node.js. It understands your code's dependency graph better than anyone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ideal for:&lt;/strong&gt; Large-scale enterprises and complex ecosystems that require rigorous standards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Get started now
npx create-nx-workspace@latest

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Comparison Table: Quick Decision Guide
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Turborepo&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Lerna&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Nx&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High (Go-based)&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Growing&lt;/td&gt;
&lt;td&gt;Massive&lt;/td&gt;
&lt;td&gt;Established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Main Focus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Build/Caching&lt;/td&gt;
&lt;td&gt;Versioning&lt;/td&gt;
&lt;td&gt;Tooling/Standardization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion: What's your next move?
&lt;/h2&gt;

&lt;p&gt;There is no "silver bullet." If you want &lt;strong&gt;speed and simplicity&lt;/strong&gt;, go with &lt;strong&gt;Turborepo&lt;/strong&gt;. If you need &lt;strong&gt;power and structure&lt;/strong&gt;, &lt;strong&gt;Nx&lt;/strong&gt; is king. If you're looking for &lt;strong&gt;tradition and flexibility&lt;/strong&gt;, &lt;strong&gt;Lerna&lt;/strong&gt; is still a solid choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro-tip:&lt;/strong&gt; Explore the official documentations and test a small project in each one before migrating your entire 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%2Foiqn3kqoptv47gh3sglj.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%2Foiqn3kqoptv47gh3sglj.png" alt="builder" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔗 Useful Links to Dive Deeper:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://turbo.build/" rel="noopener noreferrer"&gt;Official Turborepo Site&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Official Nx Site&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://lerna.js.org/" rel="noopener noreferrer"&gt;Official Lerna Site&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>javascript</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I Accidentally Exposed My API Keys to 50,000 Users (And How You Can Avoid My $3,000 Mistake)</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Wed, 07 Jan 2026 13:43:10 +0000</pubDate>
      <link>https://dev.to/werliton/i-accidentally-exposed-my-api-keys-to-50000-users-and-how-you-can-avoid-my-3000-mistake-37fp</link>
      <guid>https://dev.to/werliton/i-accidentally-exposed-my-api-keys-to-50000-users-and-how-you-can-avoid-my-3000-mistake-37fp</guid>
      <description>&lt;p&gt;It was 2 AM on a Tuesday. My phone wouldn't stop buzzing.&lt;/p&gt;

&lt;p&gt;"Dude, your AWS bill is insane this month." - My CTO&lt;/p&gt;

&lt;p&gt;I rubbed my eyes, opened the AWS console, and my heart dropped. &lt;strong&gt;$2,847.63 in unexpected charges.&lt;/strong&gt; Someone had discovered my API keys buried in my React bundle and was mining cryptocurrency using my S3 buckets.&lt;/p&gt;

&lt;p&gt;The worst part? I thought I was being "secure" by using environment variables.&lt;/p&gt;

&lt;p&gt;Spoiler alert: I wasn't.&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%2Fvf8ljw4xh4zblgj5y3pi.gif" 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%2Fvf8ljw4xh4zblgj5y3pi.gif" alt="kyes" width="260" height="240"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Brutal Truth Nobody Tells Junior Devs
&lt;/h2&gt;

&lt;p&gt;Here's what they don't teach you in bootcamp: &lt;strong&gt;Everything you ship to the frontend is PUBLIC.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I mean &lt;em&gt;everything&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That &lt;code&gt;.env&lt;/code&gt; file? Public.&lt;br&gt;&lt;br&gt;
That "hidden" API key? Public.&lt;br&gt;&lt;br&gt;
That token you "obfuscated"? Still public.&lt;/p&gt;

&lt;p&gt;Let me show you exactly what I did wrong (and what you might be doing right now).&lt;/p&gt;


&lt;h2&gt;
  
  
  My Original "Secure" Code (That Wasn't Secure At All)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ What I thought was secure&lt;/span&gt;
&lt;span class="c1"&gt;// .env.production&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_STRIPE_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;sk_live_51H&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_AWS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;AKIAIOSFODNN7EXAMPLE&lt;/span&gt;

&lt;span class="c1"&gt;// src/checkout.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Stripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REACT_APP_STRIPE_SECRET&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;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charges&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="na"&gt;amount&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;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;usd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When Webpack builds your app, it literally replaces &lt;code&gt;process.env.REACT_APP_STRIPE_SECRET&lt;/code&gt; with the actual string. Anyone can open DevTools, search the bundle, and find it in ~30 seconds.&lt;/p&gt;

&lt;p&gt;Don't believe me? Try it yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open any website (including some you'd consider "professional")&lt;/li&gt;
&lt;li&gt;Hit &lt;code&gt;F12&lt;/code&gt; → Sources tab&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+F&lt;/code&gt; and search for "API" or "secret" or "key"&lt;/li&gt;
&lt;li&gt;Watch the magic happen&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Real Attack Scenarios I've Seen
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Scenario 1: The Crypto Mining Incident (My Story)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What Happened:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Hacker found my AWS credentials → Spun up 50 EC2 instances → Mined Monero for 3 days → $3K bill&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Exposed Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Found in main.bundle.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AWS_ACCESS_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AKIAIOSFODNN7EXAMPLE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AWS_SECRET_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario 2: The Startup That Lost Customer Data
&lt;/h3&gt;

&lt;p&gt;A Y Combinator startup exposed their Firebase admin SDK key in their frontend. Attacker downloaded their entire user database (200K emails, names, addresses). Company shut down within 6 months due to GDPR fines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Their Mistake:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ NEVER do this&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REACT_APP_PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REACT_APP_PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 😱&lt;/span&gt;
    &lt;span class="na"&gt;clientEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REACT_APP_CLIENT_EMAIL&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario 3: The API Bill From Hell
&lt;/h3&gt;

&lt;p&gt;Developer exposed their OpenAI API key. Someone automated 500K requests. Bill: &lt;strong&gt;$12,000 in one weekend.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Right Way: Backend as Your Security Bodyguard
&lt;/h2&gt;

&lt;p&gt;Think of your backend as a bouncer at a club. The frontend is the drunk dude trying to get in. &lt;strong&gt;Never trust the drunk dude.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture That Actually Works
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────┐
│   Frontend   │  "Hey, can I get some data?"
│   (Public)   │  + User session token only
└──────┬───────┘
       │ HTTPS
       ▼
┌──────────────┐
│   Backend    │  "Let me check if you're legit..."
│  (Private)   │  → Validates user session
└──────┬───────┘  → Uses API keys internally
       │          → Returns sanitized data
       ▼
┌──────────────┐
│  External    │
│  Services    │
└──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code Example: The Correct Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Frontend (public code)&lt;/span&gt;
&lt;span class="c1"&gt;// src/api/checkout.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&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;userToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authToken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/create-payment&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userToken&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;span class="c1"&gt;// ✅ Backend (private code)&lt;/span&gt;
&lt;span class="c1"&gt;// server/routes/payments.js&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/create-payment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authenticateUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Validate user session&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&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;Unauthorized&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;// API key stays on server - NEVER exposed&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Stripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRIPE_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentIntent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentIntents&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="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;usd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stripeCustomerId&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;paymentIntent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client_secret&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;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;Payment failed&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;strong&gt;Why This Works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend only knows about the user's session token&lt;/li&gt;
&lt;li&gt;Stripe secret key lives only on the server&lt;/li&gt;
&lt;li&gt;If token is stolen, rate limiting + expiration limits damage&lt;/li&gt;
&lt;li&gt;Server validates every request&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Excuses I Hear (And Why They're Wrong)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "But I obfuscated the code!"
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ This doesn't help&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-secret-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Still visible in bundle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Base64 isn't encryption. A 12-year-old can decode it.&lt;/p&gt;

&lt;h3&gt;
  
  
  "But it's just a read-only key!"
&lt;/h3&gt;

&lt;p&gt;Great! Now hackers can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enumerate your entire dataset&lt;/li&gt;
&lt;li&gt;Find security holes&lt;/li&gt;
&lt;li&gt;DoS your API with unlimited requests&lt;/li&gt;
&lt;li&gt;Clone your entire application&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  "But I restricted the API key to my domain!"
&lt;/h3&gt;

&lt;p&gt;Referer headers can be spoofed. CORS helps, but it's not bulletproof:&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;// Attacker's code&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://your-api.com/data&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;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;Origin&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;https://your-domain.com&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;Some APIs check this properly (Google Maps, Firebase), many don't.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You CAN Safely Expose
&lt;/h2&gt;

&lt;p&gt;Not all environment variables are evil. Here's what's actually OK:&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;// ✅ These are fine in frontend&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_API_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//api.myapp.com&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_ENVIRONMENT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;production&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_SENTRY_DSN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//public@sentry.io/123&lt;/span&gt;

&lt;span class="c1"&gt;// Google Maps with domain restrictions&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_GOOGLE_MAPS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;AIzaSyC&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// Firebase client config (with Security Rules)&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_FIREBASE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;AIzaSyD&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;REACT_APP_FIREBASE_AUTH_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firebaseapp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Rule:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If it can be abused without user authentication → Backend only&lt;br&gt;&lt;br&gt;
If it's restricted by domain/rules → Frontend OK (with caution)&lt;/p&gt;


&lt;h2&gt;
  
  
  Quick Wins: Security Checklist
&lt;/h2&gt;

&lt;p&gt;Copy-paste this into your next PR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Security Checklist&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [ ] No API keys, secrets, or tokens in frontend code
&lt;span class="p"&gt;-&lt;/span&gt; [ ] All sensitive operations go through authenticated backend routes
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Rate limiting implemented (express-rate-limit)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] CORS configured correctly
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Input validation on all endpoints
&lt;span class="p"&gt;-&lt;/span&gt; [ ] User tokens have expiration (JWT: 1-24 hours max)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] HTTPS enforced in production
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Security headers set (helmet.js)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] .env files in .gitignore
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Different credentials per environment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The $5 Solution That Saved My Ass
&lt;/h2&gt;

&lt;p&gt;After my incident, I implemented this simple middleware. It's saved me countless times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// middleware/rateLimiter.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rateLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express-rate-limit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RedisStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rate-limit-redis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rateLimit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;store&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;RedisStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;redisClient&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;windowMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 15 minutes&lt;/span&gt;
  &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Max 100 requests per window&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Too many requests, chill out bro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standardHeaders&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;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Log suspicious activity&lt;/span&gt;
    &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rate limit exceeded&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;ip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&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;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;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;Rate limit exceeded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cost: &lt;strong&gt;$5/month for Redis&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Saved: &lt;strong&gt;$3K+ in potential abuse&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Ultimate Test
&lt;/h2&gt;

&lt;p&gt;Before you deploy, do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build your production bundle: &lt;code&gt;npm run build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;build/static/js/main.*.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Search for: "key", "secret", "token", "password", "api"&lt;/li&gt;
&lt;li&gt;If you find ANYTHING sensitive → &lt;strong&gt;DO NOT DEPLOY&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bonus points: Automate this check in your CI/CD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/security-check.yml&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check for exposed secrets&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;npm run build&lt;/span&gt;
    &lt;span class="s"&gt;if grep -r "sk_live\|api_key\|secret" build/; then&lt;/span&gt;
      &lt;span class="s"&gt;echo "🚨 Found exposed secrets!"&lt;/span&gt;
      &lt;span class="s"&gt;exit 1&lt;/span&gt;
    &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real Talk: Lessons From My $3K Mistake
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Environment variables in frontend ≠ secure&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
They're just placeholders. Webpack bakes them into your bundle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security through obscurity doesn't work&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you can see it in DevTools, so can everyone else.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Your backend is your friend&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It's not "over-engineering." It's the difference between a secure app and a hacked app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rate limiting is non-negotiable&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Even if your keys are secure, someone will try to DoS you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assume breach&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Build your architecture assuming someone will find a way in. Limit the damage they can do.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  TL;DR (For My Fellow ADHD Devs)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend = Public.&lt;/strong&gt; Period.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets = Backend only.&lt;/strong&gt; No exceptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User authentication ≠ API authentication.&lt;/strong&gt; Don't mix them up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limit everything.&lt;/strong&gt; Your wallet will thank you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test before deploy.&lt;/strong&gt; &lt;code&gt;grep&lt;/code&gt; your bundle for secrets.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Resources That Actually Helped Me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP Top 10&lt;/a&gt; - Security fundamentals&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/express-rate-limit/express-rate-limit" rel="noopener noreferrer"&gt;express-rate-limit&lt;/a&gt; - Easy rate limiting&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://helmetjs.github.io/" rel="noopener noreferrer"&gt;helmet.js&lt;/a&gt; - Security headers made easy&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/awslabs/git-secrets" rel="noopener noreferrer"&gt;git-secrets&lt;/a&gt; - Prevent committing secrets&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Got war stories about exposed API keys? Drop them in the comments. Let's learn from each other's expensive mistakes. 😅&lt;/p&gt;

&lt;p&gt;And hey, if this saved you from a $3K AWS bill, maybe buy me a coffee? ☕&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow me &lt;a href="https://dev.to/werliton"&gt;@werliton&lt;/a&gt; for more hard-learned lessons in web development.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; If you're thinking "this won't happen to me" - that's exactly what I thought. Don't be 2 AM me, frantically Googling "how to revoke AWS keys." Be better. Secure your shit. 🔒&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>frontend</category>
      <category>security</category>
    </item>
    <item>
      <title>Migrating a Static HTML/CSS/JS Project to React Using Vite - A Step-by-Step Guide</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Wed, 05 Nov 2025 14:50:00 +0000</pubDate>
      <link>https://dev.to/werliton/migrating-a-static-htmlcssjs-project-to-react-using-vite-a-step-by-step-guide-a7m</link>
      <guid>https://dev.to/werliton/migrating-a-static-htmlcssjs-project-to-react-using-vite-a-step-by-step-guide-a7m</guid>
      <description>&lt;p&gt;This article presents a concise, academic, and practical step-by-step procedure to convert an existing static website (HTML, CSS, JavaScript) into a React application scaffolded with Vite. The goal is to provide a reproducible pathway that emphasizes conceptual clarity and pragmatic code transformations. Each step includes precise actions and example code snippets intended to be executed directly in a typical development environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js and npm (or Yarn) installed.&lt;/li&gt;
&lt;li&gt;Basic familiarity with HTML, CSS, and vanilla JavaScript.&lt;/li&gt;
&lt;li&gt;A working copy of the original static site (HTML files, CSS, JS, and assets).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Resume
&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%2Fdk4su5njv83fek3l179g.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%2Fdk4su5njv83fek3l179g.png" alt="res" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Initialize a &lt;a href="https://vite.dev/guide/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; React Project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a new Vite React project in a fresh directory.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Using npm&lt;/span&gt;
npm create vite@latest my-react-site &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react

&lt;span class="c"&gt;# Or using Yarn&lt;/span&gt;
yarn create vite my-react-site &lt;span class="nt"&gt;--template&lt;/span&gt; react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install dependencies and open the project in your editor.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-react-site
npm &lt;span class="nb"&gt;install
&lt;/span&gt;code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The generated scaffold provides an entry point (&lt;code&gt;index.html&lt;/code&gt;), a &lt;code&gt;main.jsx&lt;/code&gt; or &lt;code&gt;main.tsx&lt;/code&gt; (if TypeScript template chosen), an &lt;code&gt;App.jsx&lt;/code&gt;, and a development server configured via Vite.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Import the Static Site into the New Structure
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Copy static assets (images, fonts, icons) from the original project into &lt;code&gt;src/assets/&lt;/code&gt; (or &lt;code&gt;public/&lt;/code&gt; if you want them available as static assets).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transfer CSS files into &lt;code&gt;src/styles/&lt;/code&gt; or convert global styles into &lt;code&gt;src/index.css&lt;/code&gt;. If the original site used multiple CSS files, consolidate or maintain them under &lt;code&gt;src/styles/&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move any plain JavaScript utilities into &lt;code&gt;src/utils/&lt;/code&gt; as plain modules. These will later be imported into components as needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example file layout after transfer&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-react-site/
├── index.html
├── package.json
└── src/
    ├── assets/
    │   └── logo.png
    ├── styles/
    │   └── main.css
    ├── utils/
    │   └── helpers.js
    ├── main.jsx
    └── App.jsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Understand and Adapt &lt;code&gt;index.html&lt;/code&gt; and the Entry Point
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Inspect the Vite &lt;code&gt;index.html&lt;/code&gt;. It contains the root element where React will mount, e.g. &lt;code&gt;&amp;lt;div id="root"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Vite, &lt;code&gt;index.html&lt;/code&gt; is a template. Keep only the static HTML head content (meta tags, title, link to favicon) and let React manage the DOM under the root element.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm &lt;code&gt;main.jsx&lt;/code&gt; mounts the React application:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/main.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRoot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/main.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Migrate the Page Markup into &lt;code&gt;App.jsx&lt;/code&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open&lt;/strong&gt; a representative HTML page from the original site. Copy the body structure that composes the user interface into &lt;code&gt;App.jsx&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Convert static HTML to JSX syntax&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;class&lt;/code&gt; with &lt;code&gt;className&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Close void elements (e.g., &lt;code&gt;&amp;lt;img /&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Convert inline event handlers (e.g., &lt;code&gt;onclick&lt;/code&gt;) into React props (&lt;code&gt;onClick&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Ensure attribute names follow JSX conventions (&lt;code&gt;for&lt;/code&gt; → &lt;code&gt;htmlFor&lt;/code&gt;, &lt;code&gt;tabindex&lt;/code&gt; → &lt;code&gt;tabIndex&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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%2F7dporeahvzcojzw107lb.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%2F7dporeahvzcojzw107lb.png" alt="transf" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; To speed up conversion of large chunks of HTML to valid JSX, you can use the free online tool &lt;a href="https://transform.tools/html-to-jsx" rel="noopener noreferrer"&gt;HTML to JSX Converter&lt;/a&gt; provided by Ritz078. On that site, you paste your static HTML in one panel and it instantly outputs JSX in the other panel. It also offers toggles and settings to adjust conversion behavior for React Native or SVG. (&lt;a href="https://transform.tools/html-to-jsx" rel="noopener noreferrer"&gt;transform.tools&lt;/a&gt;)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Example conversion&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/App.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/Header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Footer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/Footer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/main.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hero"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Original Site Title&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Introductory text ported from static HTML.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Additional content goes here */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Footer&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Componentize the Interface
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Identify logical UI sections: header, footer, navigation, card/list items, hero, forms, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;code&gt;src/components/&lt;/code&gt; directory and implement each section as a functional component. Keep components small and focused.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Header example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Header.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;logo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../assets/logo.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"site-header"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Site Logo"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#home"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#about"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Import and use the components from &lt;code&gt;App.jsx&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  6. Replace Inline Scripts with React State and Handlers
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Identify interactive features implemented in vanilla JavaScript (e.g., toggles, show/hide, simple tab behavior).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Translate those behaviors into React using &lt;code&gt;useState&lt;/code&gt; and handler functions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Simple toggle example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ToggleText&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setVisible&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setVisible&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&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;!&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hide&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;Show&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; details
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Details converted from original script.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Remove global DOM queries (&lt;code&gt;document.querySelector&lt;/code&gt;) and inline script tags; prefer local component state and props.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  7. Convert Data-Driven Lists to &lt;code&gt;.map()&lt;/code&gt; Rendering
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If the original site renders repeated elements (cards, lists), encode the data as an array of objects in a module or within component state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Render the list using &lt;code&gt;.map()&lt;/code&gt; and supply a stable &lt;code&gt;key&lt;/code&gt; for each element.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;List example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/data/items.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="s1"&gt;Item 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Description 1&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="s1"&gt;Item 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Description 2&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/ItemList.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../data/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ItemList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. Handle Forms as Controlled Components
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Replace native form scripts with controlled form inputs to capture user input in React state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Controlled form example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubscribeForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email submitted:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setEmail&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Email&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Subscribe&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Replace any inline validation logic with state-driven validation or use a lightweight form library when complexity grows.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  9. Integrate Utilities and External Scripts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Utilities previously loaded via script tags (e.g., helper functions) should be converted into ES modules and imported where needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For third-party libraries that manipulate the DOM directly (e.g., jQuery plugins), prefer React-compatible alternatives or wrap them carefully within &lt;code&gt;useEffect&lt;/code&gt; to avoid conflicts with React's rendering model.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  10. Style Management
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;If the original project used global CSS, continue to use it by importing the stylesheet in &lt;code&gt;main.jsx&lt;/code&gt; or &lt;code&gt;App.jsx&lt;/code&gt;. For improved encapsulation, consider:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/css-modules/css-modules" rel="noopener noreferrer"&gt;CSS Modules&lt;/a&gt;: &lt;code&gt;Component.module.css&lt;/code&gt; and import as &lt;code&gt;styles&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;CSS-in-JS: styled-components or similar libraries.&lt;/li&gt;
&lt;li&gt;Utility frameworks: &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Maintain accessibility attributes (ARIA) and semantic HTML elements when converting markup.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example CSS import&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/main.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/main.css&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;h2&gt;
  
  
  11. Optional: Introduce Client-Side Routing
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;If the original project had multiple pages and you wish to maintain the single-page application model, install and configure a &lt;a href="https://reactrouter.com/" rel="noopener noreferrer"&gt;routing library&lt;/a&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-router-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Example minimal router setup:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/App.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/Home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/About&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Home&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"about"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;About&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  12. Project Organization and Best Practices
&lt;/h2&gt;

&lt;p&gt;Adopt a clear folder structure to maintain scalability and readability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── assets/
├── components/
├── data/
├── pages/
├── styles/
├── utils/
├── App.jsx
└── main.jsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Guiding principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small, single-responsibility components.&lt;/li&gt;
&lt;li&gt;Lift state up only when necessary.&lt;/li&gt;
&lt;li&gt;Prefer props for data flow and callbacks for child-to-parent communication.&lt;/li&gt;
&lt;li&gt;Use descriptive filenames and consistent naming conventions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  13. Build and Deployment
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Verify the production build process provided by Vite.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# build for production&lt;/span&gt;
npm run build

&lt;span class="c"&gt;# preview production build locally&lt;/span&gt;
npm run preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Deploy to modern static hosts (for example: &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;, &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;, or &lt;a href="//pages.github.com"&gt;GitHub Pages&lt;/a&gt;). Ensure correct configuration of the host to serve &lt;code&gt;index.html&lt;/code&gt; for client-side routing (if routing is used).&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;This guide articulates a direct, repeatable transformation from a static HTML/CSS/JS site into a component-based React application using Vite. The process emphasizes incremental migration: import assets and global styles, port markup to JSX, componentize, replace direct DOM manipulation with React state and handlers, and reorganize code for maintainability. Adhering to these steps produces a React application that preserves the original design while gaining modularity, testability, and scalability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Refs:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pt-br.react.dev/learn/creating-a-react-app" rel="noopener noreferrer"&gt;https://pt-br.react.dev/learn/creating-a-react-app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vite.dev/guide/" rel="noopener noreferrer"&gt;https://vite.dev/guide/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://transform.tools/html-to-jsx" rel="noopener noreferrer"&gt;https://transform.tools/html-to-jsx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>react</category>
    </item>
    <item>
      <title>Master Regex for Free: 3 Fun and Interactive Sites Every Dev Should Know</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Fri, 10 Oct 2025 19:27:51 +0000</pubDate>
      <link>https://dev.to/werliton/master-regex-for-free-3-fun-and-interactive-sites-every-dev-should-know-13jl</link>
      <guid>https://dev.to/werliton/master-regex-for-free-3-fun-and-interactive-sites-every-dev-should-know-13jl</guid>
      <description>&lt;p&gt;💡 Learning Regex doesn't have to be a confusing mess of slashes and symbols. It can be visual, interactive, and engaging - without paying a cent.&lt;/p&gt;

&lt;p&gt;Here are 3 of the best free and interactive websites that turn the dreaded Regular Expression into a game. Whether you're trying to validate emails, scrape data, or just decipher patterns, these tools will level up your Regex skills while you play.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. RegexOne &lt;a href="https://regexone.com/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;
&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%2Fptzvnxdungjnclchw4ze.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%2Fptzvnxdungjnclchw4ze.png" alt="RegexOne" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learn the fundamentals of Regex with progressive, step-by-step interactive lessons. You solve simple challenges, like finding the first occurrence of a word, all the way up to complex concepts like capturing groups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's awesome:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ideal for absolute beginners starting from square one.
&lt;/li&gt;
&lt;li&gt;A lesson-by-lesson approach with immediate feedback on exercises.
&lt;/li&gt;
&lt;li&gt;Focuses on simple, practical examples.
&lt;/li&gt;
&lt;li&gt;Extremely clean interface with no distractions.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommended for:&lt;/strong&gt; Beginners to Intermediate&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Totally free. No signup required.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. RegexRoo (Wildcard Challenges) 🐾&lt;a href="https://www.regexroo.com/wildcard" rel="noopener noreferrer"&gt;Here&lt;/a&gt;
&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%2F5xohj9dhcotib20ao0d0.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%2F5xohj9dhcotib20ao0d0.png" alt="RegexRoo " width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Help the "kangaroo" find the patterns! RegexRoo focuses on a game style where you must use wildcards, quantifiers, and character classes to "capture" the correct string from a wall of text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's awesome:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specific focus on essential patterns like the wildcard (.), *, and +.
&lt;/li&gt;
&lt;li&gt;Immediate visual feedback shows exactly which characters your expression is matching.
&lt;/li&gt;
&lt;li&gt;The gamified approach (pattern treasure hunt) makes practice feel addictive.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommended for:&lt;/strong&gt; All levels (Great for honing speed and accuracy)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;100% free and interactive.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. RegexLearn &lt;a href="https://regexlearn.com/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;
&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%2Fqgp5uzk5lngww2phougd.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%2Fqgp5uzk5lngww2phougd.png" alt="RegexLearn" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This site provides a highly structured and comprehensive Regex course. It offers a complete learning path, integrated quick references, and tutorials for advanced techniques.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's awesome:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comes with an integrated Cheat Sheet for instant symbol lookup.
&lt;/li&gt;
&lt;li&gt;Covers advanced topics like Assertions (Lookaheads/Lookbehinds) clearly.
&lt;/li&gt;
&lt;li&gt;Allows practice in the style of Regex101 (the industry-standard tool), prepping you for professional use.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommended for:&lt;/strong&gt; Intermediate to Advanced (To master the more obscure tricks)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Free to use. Access essential resources with no login required.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Which of these three interactive sites are you going to tackle first?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Drop a comment below with the first pattern you plan to master, and be sure to follow for the next part of the Regex Master series!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>regex</category>
    </item>
    <item>
      <title>Stop Waiting for APIs: Unlock Instant Speed with React's Optimistic Updates</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Thu, 02 Oct 2025 13:47:03 +0000</pubDate>
      <link>https://dev.to/werliton/optimistic-updates-in-react-how-they-work-and-why-theyre-so-fast-44g7</link>
      <guid>https://dev.to/werliton/optimistic-updates-in-react-how-they-work-and-why-theyre-so-fast-44g7</guid>
      <description>&lt;p&gt;Tchaca was developing a new feature and noticed something annoying: every time a user clicked "like," the interface would take a few seconds to respond while waiting for the server. During that time, the screen seemed frozen, and the experience was frustrating.&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%2F86sekxknenoazvystty8.gif" 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%2F86sekxknenoazvystty8.gif" alt="wait" width="466" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;She thought, "Do I really need to wait for the server to show what the user already knows they requested?" 🤔&lt;/p&gt;

&lt;p&gt;That's when she discovered &lt;strong&gt;optimistic updates&lt;/strong&gt; - a way to make the interface feel more fluid, giving the impression of an immediate response, even before the server actually confirms it.&lt;/p&gt;




&lt;p&gt;In web applications, the latency between the client and server can significantly impact user experience. &lt;strong&gt;Optimistic updates&lt;/strong&gt; are a powerful technique to improve perceived performance by updating the interface &lt;strong&gt;before the server confirms the action&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concept
&lt;/h2&gt;

&lt;p&gt;An optimistic &lt;strong&gt;update involves immediately updating the local state after a user action&lt;/strong&gt;, assuming the server operation will succeed. If the server confirms, the UI remains unchanged; if it fails, the update is rolled back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Result
&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%2F71difm239u2114xqxvp7.gif" 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%2F71difm239u2114xqxvp7.gif" alt="res" width="640" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This technique is especially useful for fast interactions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Liking posts&lt;/li&gt;
&lt;li&gt;Adding items to a shopping cart&lt;/li&gt;
&lt;li&gt;Voting in polls&lt;/li&gt;
&lt;li&gt;Updating lists&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Perceived speed&lt;/strong&gt;: users see changes instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smooth experience&lt;/strong&gt;: avoids a “frozen” UI while waiting for the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy rollback&lt;/strong&gt;: reversing a failed action is straightforward.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Practical Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Without Optimistic Update
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLikes&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addLike&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fakeApiCall&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setLikes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;likes&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Updates only after server response&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; Likes&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;addLike&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Like&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this approach, the UI only updates after the server responds, causing noticeable delays if the API is slow.&lt;/p&gt;




&lt;h3&gt;
  
  
  With Optimistic Update
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLikes&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addLike&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Update locally immediately&lt;/span&gt;
    &lt;span class="nf"&gt;setLikes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Call the server&lt;/span&gt;
    &lt;span class="nf"&gt;fakeApiCall&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Rollback if there’s an error&lt;/span&gt;
      &lt;span class="nf"&gt;setLikes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;likes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; Likes&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;addLike&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Like&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Technical tip&lt;/strong&gt;: using the callback version of &lt;code&gt;setLikes (prev =&amp;gt; prev + 1)&lt;/code&gt; ensures state consistency even with rapid multiple interactions.&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Efficient rollback&lt;/strong&gt;: always plan to revert the UI on errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid inconsistencies&lt;/strong&gt;: use previous-state updates (&lt;code&gt;prev&lt;/code&gt;) to prevent race conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend synchronization&lt;/strong&gt;: logging or event queues can help reconcile states if multiple updates fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache management&lt;/strong&gt;: libraries like &lt;strong&gt;React Query&lt;/strong&gt;, &lt;strong&gt;SWR&lt;/strong&gt;, or &lt;strong&gt;Apollo Client&lt;/strong&gt; provide built-in support for optimistic updates and automatic server sync.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  When to Use
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fast and predictable server operations.&lt;/li&gt;
&lt;li&gt;Interactions that don’t require immediate confirmation.&lt;/li&gt;
&lt;li&gt;Cases where a fast UX outweighs immediate absolute consistency.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Technical Summary:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Optimistic updates&lt;/code&gt; in React let the local state &lt;strong&gt;be updated before the server responds&lt;/strong&gt;, improving UX and perceived performance. If the server operation fails, the UI is reverted, ensuring consistency.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Unlock Your Voice: 5 TED-Style Communication Techniques for Beg</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Thu, 25 Sep 2025 14:58:00 +0000</pubDate>
      <link>https://dev.to/werliton/unlock-your-voice-5-ted-style-communication-techniques-for-beg-1m2j</link>
      <guid>https://dev.to/werliton/unlock-your-voice-5-ted-style-communication-techniques-for-beg-1m2j</guid>
      <description>&lt;p&gt;Now that your voice is warmed up, let’s explore &lt;strong&gt;strategies used by top speakers&lt;/strong&gt;, especially in TED Talks:&lt;/p&gt;




&lt;h3&gt;
  
  
  1. 🧭 Start with a Story
&lt;/h3&gt;

&lt;p&gt;Stories build connection. Begin your talk with a personal anecdote or metaphor that relates to your topic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: “When I broke my first production code, I learned more about communication than JavaScript…”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  2. ⏳ Use Strategic Pauses
&lt;/h3&gt;

&lt;p&gt;Pauses create impact. They help your audience absorb key points and make your speech feel more confident.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: After a powerful statement, pause. Let silence do the work.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  3. 🧠 Simplify Your Language
&lt;/h3&gt;

&lt;p&gt;Avoid jargon when explaining to beginners or non-tech audiences. Use analogies and simple examples.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: “Think of your code like a cake recipe. If one ingredient is missing, the result won’t be what you expected.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  4. 🎯 Focus on One Big Idea
&lt;/h3&gt;

&lt;p&gt;Great talks revolve around &lt;strong&gt;one core message&lt;/strong&gt;. Everything you say should reinforce that idea.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ask yourself: “If the audience remembers one thing, what should it be?”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  5. 🧍‍♂️ Use Body Language
&lt;/h3&gt;

&lt;p&gt;Gestures, posture, and facial expressions matter. Practice in front of a mirror or record yourself to observe your non-verbal cues.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TED speakers use the stage as part of their message. You can use your space too!&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;These exercises and techniques are simple but powerful. If you're starting out in tech, remember: &lt;strong&gt;communicating well is just as important as coding well&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Train your voice like you train your code. And if you want to go further, start recording short videos explaining tech concepts — it’s a fast track to becoming a confident communicator.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Did you know any of these techniques already? Got a favorite one? Share in the comments below! 👇&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>softskills</category>
      <category>communication</category>
    </item>
    <item>
      <title>How We Solved Commit Chaos with a Custom Commitlint Rule</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Thu, 25 Sep 2025 14:55:00 +0000</pubDate>
      <link>https://dev.to/werliton/how-we-solved-commit-chaos-with-a-custom-commitlint-rule-488n</link>
      <guid>https://dev.to/werliton/how-we-solved-commit-chaos-with-a-custom-commitlint-rule-488n</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: Everyone Commits Differently
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;You know that moment when you're reviewing code and think,&lt;br&gt;
"Wait… what Jira task is this commit even related to?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah, we lived that.&lt;/p&gt;

&lt;p&gt;In our team, each Jira task had a clear ID like &lt;code&gt;TWSF-1234&lt;/code&gt;, but our commit messages? A wild mix. Some had the task ID, some didn’t. Some were super descriptive, others… not so much.&lt;/p&gt;

&lt;p&gt;We knew we needed to fix this. Not just for ourselves, but for future us - the ones debugging, deploying, or trying to understand what happened two sprints ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 The Idea: Let’s Automate the Standard
&lt;/h2&gt;

&lt;p&gt;We didn’t want to rely on memory or discipline alone. We wanted a system that would guide developers to write consistent, traceable commit messages - without being annoying.&lt;/p&gt;

&lt;p&gt;That’s when we found &lt;code&gt;**Commitlint**&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Commitlint checks your commit messages and makes sure they follow a set of rules. You can use standard rules, or - and this is where it gets fun - you can write your own.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Our Custom Rule: Enforcing Jira Task IDs
&lt;/h2&gt;

&lt;p&gt;We created a rule that checks if the scope of the commit message matches our Jira task format: &lt;code&gt;TWSF-&amp;lt;number&amp;gt;&lt;/code&gt;. If it doesn’t, the commit is rejected with a friendly message.&lt;/p&gt;

&lt;p&gt;Here’s what our config looks like:&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extends&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;@commitlint/config-conventional&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;rules&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;twsf-task-scope&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;always&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;plugins&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="na"&gt;rules&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;twsf-task-scope&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;scope&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^TWSF-&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+$/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Scope must follow the pattern TWSF-&amp;lt;task-number&amp;gt;, e.g., TWSF-1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;];&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="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;
  
  
  ✅ Valid commit:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;feat&lt;span class="o"&gt;(&lt;/span&gt;TWSF-1234&lt;span class="o"&gt;)&lt;/span&gt;: add &lt;span class="nb"&gt;export &lt;/span&gt;button to report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ❌ Invalid commit:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fix&lt;span class="o"&gt;(&lt;/span&gt;report&lt;span class="o"&gt;)&lt;/span&gt;: fix &lt;span class="nb"&gt;export &lt;/span&gt;bug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second one gets blocked with a clear message telling the dev what to fix.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Sharing the Rule Across Projects
&lt;/h2&gt;

&lt;p&gt;We didn’t stop there. To make this reusable across all our projects, we packaged the rule into a &lt;strong&gt;private npm library&lt;/strong&gt;. Now, any team in the company can install it and instantly get the same commit standards.&lt;/p&gt;

&lt;p&gt;Here’s how we did it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a new npm package with the config.&lt;/li&gt;
&lt;li&gt;Published it privately using our company scope.&lt;/li&gt;
&lt;li&gt;In each project, we just install and extend it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @ourcompany/commitlint-config-twsf

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

&lt;/div&gt;



&lt;p&gt;And in &lt;code&gt;commitlint.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;module.exports &lt;span class="o"&gt;=&lt;/span&gt; require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@ourcompany/commitlint-config-twsf'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 The Result: Clean, Consistent, Traceable Commits
&lt;/h2&gt;

&lt;p&gt;Now every commit tells a story. It’s linked to a Jira task, easy to understand, and consistent across the board. No more guessing, no more digging.&lt;/p&gt;




&lt;p&gt;If your team struggles with messy commit messages, I highly recommend trying this out. It’s simple, effective, and makes a real difference in day-to-day development.&lt;/p&gt;

&lt;p&gt;Want help setting it up? Drop a comment or message me — happy to share what worked for us.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>You’re Not Using AI Prompts to Their Full Potential - Meet RTF and BAB</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Tue, 23 Sep 2025 14:58:00 +0000</pubDate>
      <link>https://dev.to/werliton/youre-not-using-ai-prompts-to-their-full-potential-meet-rtf-and-bab-a9a</link>
      <guid>https://dev.to/werliton/youre-not-using-ai-prompts-to-their-full-potential-meet-rtf-and-bab-a9a</guid>
      <description>&lt;p&gt;Prompt engineering is evolving fast, and while TAG and RISE are powerful tools, there are other frameworks that can help you get even better results from AI models. In this post, we’ll explore two lesser-known but super useful models: &lt;strong&gt;RTF&lt;/strong&gt; and &lt;strong&gt;BAB&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Prompt RTF Framework
&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%2Fg1uu6rpsnbx66jh698ki.gif" 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%2Fg1uu6rpsnbx66jh698ki.gif" alt="fomt" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RTF&lt;/strong&gt; stands for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role&lt;/strong&gt;: Define the AI’s persona or function.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task&lt;/strong&gt;: Describe the task you want it to perform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Format&lt;/strong&gt;: Specify the format of the output.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Example:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prompt&lt;/strong&gt;: Act as a UX designer. Create a checklist for onboarding screens. Show me in bullet points.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role&lt;/strong&gt;: UX designer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task&lt;/strong&gt;: Create a checklist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Format&lt;/strong&gt;: Bullet points&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;This framework is great when you want &lt;strong&gt;clarity and structure&lt;/strong&gt; in the output.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Prompt BAB Framework
&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%2Frfhupw7e7s5yswife0rq.gif" 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%2Frfhupw7e7s5yswife0rq.gif" alt="bf" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BAB&lt;/strong&gt; stands for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before&lt;/strong&gt;: Explain the current situation or problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After&lt;/strong&gt;: Describe the desired outcome.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bridge&lt;/strong&gt;: Ask the AI to create a solution that connects the two.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Example:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prompt&lt;/strong&gt;: Before: I struggle to stay focused while coding.&lt;br&gt;&lt;br&gt;
After: I want to work in 90-minute deep focus sessions.&lt;br&gt;&lt;br&gt;
Bridge: Suggest a daily routine and tools to help me get there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;BAB is perfect for &lt;strong&gt;problem-solving&lt;/strong&gt;, &lt;strong&gt;goal setting&lt;/strong&gt;, and &lt;strong&gt;behavioral change&lt;/strong&gt; prompts.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 When to Use RTF vs BAB?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;RTF&lt;/th&gt;
&lt;th&gt;BAB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structured output&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Role-based tasks&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Personal development&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Problem-solving&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative formats&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;RTF and BAB are great additions to your prompt engineering toolkit. Whether you're building apps, writing content, or just trying to get better answers from ChatGPT, these frameworks help you &lt;strong&gt;guide the AI more effectively&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Try mixing them with other techniques like few-shot prompting or chain-of-thought reasoning for even better results.&lt;/p&gt;

&lt;p&gt;Happy prompting! 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Unlock Your Voice: 8 Vocal Exercises Communication Techniques for Beginner Developers</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Tue, 23 Sep 2025 14:49:00 +0000</pubDate>
      <link>https://dev.to/werliton/unlock-your-voice-8-vocal-exercises-communication-techniques-for-beginner-developers-2l8d</link>
      <guid>https://dev.to/werliton/unlock-your-voice-8-vocal-exercises-communication-techniques-for-beginner-developers-2l8d</guid>
      <description>&lt;p&gt;Ever felt your voice freeze when trying to explain an idea? Or that your speech doesn’t keep up with your thoughts during a presentation? If so, this post is for you!&lt;/p&gt;

&lt;p&gt;Communication is a &lt;strong&gt;critical skill&lt;/strong&gt; for developers — whether you're explaining a solution, defending a technical decision, or sharing knowledge. The good news? You can train it!&lt;/p&gt;

&lt;p&gt;Here are &lt;strong&gt;8 practical vocal exercises&lt;/strong&gt; to unlock your voice and &lt;strong&gt;5 powerful techniques&lt;/strong&gt; used by world-class speakers to improve your communication — even if you're just starting out.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎤 Part 1: Vocal Exercises to Unlock Your Speech
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. 🎶 The Power of “La La La”
&lt;/h3&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%2F18d6oa64lg0l1btxisyv.gif" 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%2F18d6oa64lg0l1btxisyv.gif" alt="hb" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inspired by the movie &lt;em&gt;Sister Act&lt;/em&gt;, this exercise helps loosen up your tongue. Watch "Oh Happy Day - Sister Act". she teaches a youth choir to warm up with “la la la”.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: Imagine you're part of the choir and follow along. It’s fun and surprisingly effective!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  2. 💨 Lip Trills
&lt;/h3&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%2F7hp0vin6ktm3rl6hu225.gif" 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%2F7hp0vin6ktm3rl6hu225.gif" alt="lip" width="480" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before any talk or recording, make a motorboat sound by blowing air through your lips. Repeat 5 times, with breathing pauses.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This relaxes your facial muscles and improves articulation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  3. ✏️ The Pen Exercise
&lt;/h3&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%2Fetsdsdziibv9f4o2ys9z.gif" 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%2Fetsdsdziibv9f4o2ys9z.gif" alt="pen" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Place a pen horizontally between your teeth and try speaking simple phrases. This forces your mouth to articulate more clearly and slows down your speech.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Great for improving clarity and rhythm!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  4. 🔊 SI FU XI PA
&lt;/h3&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%2Fv5w3l604quu5e2y8uvul.gif" 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%2Fv5w3l604quu5e2y8uvul.gif" alt="ss" width="243" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Say these syllables with emphasis, stressing each one individually: &lt;strong&gt;SI&lt;/strong&gt;, &lt;strong&gt;FU&lt;/strong&gt;, &lt;strong&gt;XI&lt;/strong&gt;, &lt;strong&gt;PA&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Helps train vocal tone and control.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  5. 👅 Tongue 360º
&lt;/h3&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%2F5mobfa5byddmosejzpxc.gif" 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%2F5mobfa5byddmosejzpxc.gif" alt="tg" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Move your tongue in a circular motion inside your mouth. This relaxes your jaw, cheeks, and chin.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Perfect for reducing tension before speaking.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  6. 🧠 Tongue Twister #1
&lt;/h3&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%2Fhqrt42yk7xt617l6jypv.gif" 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%2Fhqrt42yk7xt617l6jypv.gif" alt="tt" width="210" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In a nest of gagafos, there are seven gagafinhos...&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Say it as fast as you can without messing up — or mess up and try again!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Classic exercise to loosen up your mouth and improve verbal agility.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  7. 🧵 Tongue Twister #2
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The rat gnawed the rich robe of the king of Rome...&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Focus on the &lt;strong&gt;R&lt;/strong&gt; sound — it demands precise articulation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Excellent for improving diction!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  8. 🕷️ Tongue Twister #3
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The spider scratches the frog. The frog scratches the spider...&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Try saying it fast and clearly. It’s a challenge, but it’s a workout for your speech muscles.&lt;/p&gt;




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

&lt;p&gt;These exercises and techniques are simple but powerful. If you're starting out in tech, remember: &lt;strong&gt;communicating well is just as important as coding well&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Train your voice like you train your code. And if you want to go further, start recording short videos explaining tech concepts — it’s a fast track to becoming a confident communicator.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Did you know any of these techniques already? Got a favorite one? Share in the comments below! 👇&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>voice</category>
      <category>skill</category>
      <category>communication</category>
    </item>
    <item>
      <title>Why Senior Frontend Devs Use jest.spyOn - And You Should Too</title>
      <dc:creator>Werliton Silva</dc:creator>
      <pubDate>Thu, 18 Sep 2025 14:58:00 +0000</pubDate>
      <link>https://dev.to/werliton/why-senior-frontend-devs-use-jestspyon-and-you-should-too-5411</link>
      <guid>https://dev.to/werliton/why-senior-frontend-devs-use-jestspyon-and-you-should-too-5411</guid>
      <description>&lt;p&gt;If you're writing tests for frontend applications and still not using &lt;code&gt;jest.spyOn&lt;/code&gt;, you're missing out on one of the most powerful tools Jest offers.&lt;/p&gt;

&lt;p&gt;Let me show you &lt;strong&gt;why&lt;/strong&gt;, &lt;strong&gt;when&lt;/strong&gt;, and &lt;strong&gt;how&lt;/strong&gt; to use it — with real examples that will level up your testing game.&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%2Fz1gc6nuko1l8elyb3647.gif" 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%2Fz1gc6nuko1l8elyb3647.gif" alt="test" width="500" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 What is &lt;code&gt;jest.spyOn&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;jest.spyOn&lt;/code&gt; lets you &lt;strong&gt;monitor&lt;/strong&gt; and &lt;strong&gt;control&lt;/strong&gt; how a function behaves during a test — without changing the original implementation.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Check if a function was called&lt;/li&gt;
&lt;li&gt;Control its return value&lt;/li&gt;
&lt;li&gt;Track how many times it was triggered&lt;/li&gt;
&lt;li&gt;Restore it after the test&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Example 1: Spying on a Utility Function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// utils/date.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formatDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/Greeting.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;formatDate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Greeting&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nx"&gt;Today&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;formatDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;dateUtils&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calls formatDate with correct date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateUtils&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;formatDate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;render&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;Greeting&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2025-09-16&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2025-09-16&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockRestore&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;
  
  
  🧪 Example 2: Mocking a Function Temporarily
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;September 16, 2025&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders mocked date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateUtils&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;formatDate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;September 16, 2025&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&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;Greeting&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/September 16, 2025/&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockRestore&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;
  
  
  🧠 When to Use &lt;code&gt;jest.spyOn&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Use it when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want to &lt;strong&gt;observe&lt;/strong&gt; a function without replacing it&lt;/li&gt;
&lt;li&gt;You need to &lt;strong&gt;mock&lt;/strong&gt; a function temporarily&lt;/li&gt;
&lt;li&gt;You’re testing &lt;strong&gt;side effects&lt;/strong&gt; or &lt;strong&gt;interactions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You want to &lt;strong&gt;avoid testing implementation details&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚫 When &lt;em&gt;Not&lt;/em&gt; to Use It
&lt;/h2&gt;

&lt;p&gt;Avoid &lt;code&gt;jest.spyOn&lt;/code&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re testing pure functions directly (use &lt;code&gt;jest.fn()&lt;/code&gt; instead)&lt;/li&gt;
&lt;li&gt;You’re mocking entire modules (use &lt;code&gt;jest.mock()&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📌 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always &lt;code&gt;mockRestore()&lt;/code&gt; after your test to avoid side effects&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;spy.mockImplementation()&lt;/code&gt; for custom behavior&lt;/li&gt;
&lt;li&gt;Keep your tests focused: spy only what’s necessary&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;&lt;code&gt;jest.spyOn&lt;/code&gt; is like a magnifying glass for your tests — it lets you zoom in on behavior without rewriting code. Use it wisely, and your tests will be cleaner, smarter, and more maintainable.&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%2Fw7iagjx96cg86vqs47vk.gif" 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%2Fw7iagjx96cg86vqs47vk.gif" alt="tt" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Liked this?&lt;/strong&gt; Follow me for more practical testing tips and frontend insights. Let’s write code that’s not just functional — but testable and reliable.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
