<?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: Samit Kapoor</title>
    <description>The latest articles on DEV Community by Samit Kapoor (@samitkapoor).</description>
    <link>https://dev.to/samitkapoor</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%2F942902%2F4cd2e8b0-074b-4a0c-9e0b-a930dd46b9b6.jpg</url>
      <title>DEV Community: Samit Kapoor</title>
      <link>https://dev.to/samitkapoor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samitkapoor"/>
    <language>en</language>
    <item>
      <title>Prompt Engineering 101: Master the Art of Asking AI the Right Way</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 05 Jul 2025 17:00:33 +0000</pubDate>
      <link>https://dev.to/samitkapoor/prompt-engineering-101-master-the-art-of-asking-ai-the-right-way-3mco</link>
      <guid>https://dev.to/samitkapoor/prompt-engineering-101-master-the-art-of-asking-ai-the-right-way-3mco</guid>
      <description>&lt;p&gt;Lately, I've been diving into building AI-powered web applications to boost my own productivity. One thing has become crystal clear: the barrier to entry for building anything has dropped dramatically. In this AI age, anyone can create, learning new skills is faster than ever, and information is at our fingertips.&lt;/p&gt;

&lt;p&gt;However, as we move forward, quality will be the ultimate differentiator. Half-baked products won't cut it. To truly stand out and retain users, quality is paramount. So, how can you level up your prompt engineering skills to consistently get high-quality responses from AI? Let's explore some key techniques to help you hit that sweet spot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use AI to Write Prompts (Yes, Really!)
&lt;/h2&gt;

&lt;p&gt;Okay, this might sound a little meta, but hear me out: use AI to &lt;em&gt;help&lt;/em&gt; you write better prompts. It might seem obvious, or maybe even a bit unnecessary, but it can seriously level up your results.&lt;/p&gt;

&lt;p&gt;The clearer your prompts are, the better the AI will understand what you're asking for. Unless you're a professional writer (and let's be honest, most of us aren't!), using AI to refine or even completely rewrite your prompts can make a huge difference. Think of it as having an AI assistant dedicated to making your requests crystal clear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's say you're trying to figure out how to add a progressive blur effect. You might start with a prompt like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;how to add progressive blur&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem with this prompt is that it's missing crucial context. Are you trying to add this effect in Figma? Framer? Or are you trying to implement it in a React project? What language are you using?&lt;/p&gt;

&lt;p&gt;If you feed this vague prompt to an AI and ask it to improve it, you might get something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I want to implement a progressive blur effect on images in my React project. Provide code examples and explanations for how to achieve this using CSS and JavaScript. Assume I am using a functional component approach and have basic knowledge of React hooks.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See how much more specific the refined prompt is? By providing details about the framework (React), the technologies (CSS and JavaScript), and your existing knowledge, you're much more likely to get a helpful and relevant response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zero Shot, One Shot &amp;amp; Few Shot Approach
&lt;/h2&gt;

&lt;p&gt;When it comes to prompt engineering, you'll often hear the terms "zero-shot," "one-shot," and "few-shot." What's the deal with all these "shots"?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Zero-Shot:&lt;/strong&gt; This is when you ask the AI a question or give it a task &lt;em&gt;without&lt;/em&gt; providing any examples. The AI's gotta rely on its own brainpower here.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;One-Shot:&lt;/strong&gt; This is the middle ground where you give the AI &lt;em&gt;one&lt;/em&gt; example to learn from. Think of it as a quick study guide.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Few-Shot:&lt;/strong&gt; This is when you &lt;em&gt;do&lt;/em&gt; provide the AI with a few examples of the type of output you're looking for. This helps the AI understand the vibe you're going for.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's often the case that you'll get better results with a few-shot approach, especially when you're trying to get the AI to generate content in a specific format.&lt;/p&gt;

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

&lt;p&gt;Let's say you want the AI to write a social media post. With a zero-shot prompt, you might simply ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Write a tweet about the benefits of prompt engineering.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI will likely generate &lt;em&gt;something&lt;/em&gt;, but it might not be very engaging or tailored to your specific needs.&lt;/p&gt;

&lt;p&gt;With a few-shot prompt, you could provide an example like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Here are a few example tweets about prompt engineering:&lt;/em&gt; &lt;br&gt;
&lt;em&gt;- Prompt engineering is the secret weapon for unlocking the full potential of AI! 🚀 #PromptEngineering #AI&lt;/em&gt;&lt;br&gt;
&lt;em&gt;- Want better AI results? It all starts with better prompts. Learn the art of prompt engineering! 💡 #AI #PromptHacking&lt;/em&gt;&lt;br&gt;
&lt;em&gt;- Stop wasting time on bad AI outputs! Master prompt engineering and get the results you deserve. 💪 #ArtificialIntelligence&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Now, write another tweet about the benefits of prompt engineering, following the same style and format.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By providing these examples, you're giving the AI a clear understanding of the desired tone, length, and use of hashtags.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Tradeoff:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By giving the AI examples, you're also kind of putting it in a box. It'll see your examples and try to copy that style, which can limit its creativity. It's like saying, "Hey, be creative, but only &lt;em&gt;this&lt;/em&gt; creative." So, keep that in mind! If you want something truly original, zero-shot might be the way to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  A/B Testing
&lt;/h2&gt;

&lt;p&gt;Okay, this might seem obvious, but it's important. If you're not A/B testing your prompts, you're leaving a &lt;em&gt;ton&lt;/em&gt; of potential on the table.&lt;/p&gt;

&lt;p&gt;Since there's no official "Prompt Engineering for Dummies" guide, A/B testing is how you figure out what works and what doesn't. Basically, you give the AI multiple prompts for the same desired result and see which one performs better.&lt;/p&gt;

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

&lt;p&gt;Let's say you're trying to get the AI to write a compelling product description for a new noise-canceling headphone. You could try these two prompts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Prompt A:&lt;/strong&gt; "Write a product description for noise-canceling headphones."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Prompt B:&lt;/strong&gt; "Write a persuasive and benefit-driven product description for 'Sony' noise-canceling headphones, highlighting their superior noise cancellation, comfortable design, and long battery life. Target busy professionals who work from home."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run both prompts and compare the results. Prompt B is much more specific and provides context about the target audience and key features. You'll likely get a much better product description from Prompt B.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measuring Your Results: How to Know What's Winning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, you've run your A/B tests, but how do you actually &lt;em&gt;know&lt;/em&gt; which prompt is better? Here are a few things to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Relevance:&lt;/strong&gt; Does the output actually address the prompt? Does it stay on topic?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Quality:&lt;/strong&gt; Is the writing clear, concise, and grammatically correct?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Engagement:&lt;/strong&gt; Is the output engaging and interesting to read? Would it capture someone's attention?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Usefulness:&lt;/strong&gt; Is the output actually &lt;em&gt;useful&lt;/em&gt; for its intended purpose? (e.g., does the product description effectively sell the product?)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Subjectivity:&lt;/strong&gt; Sometimes, it just comes down to your gut feeling. Which output do you &lt;em&gt;personally&lt;/em&gt; like better?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why This Matters (And Why We Don't Do It Enough):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're so used to chatting with AI, giving it one prompt, then tweaking it with followup messages. But we almost &lt;em&gt;never&lt;/em&gt; start a fresh chat with a completely different prompt. That's a mistake!&lt;/p&gt;

&lt;p&gt;The best way I've found to really nail this is to use my own product (I built an AI tool). I keep using it, tweaking the prompts, and seeing what happens. It's a win-win because I'm not only improving my prompts, but I'm also making my product better at solving my own problems.&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%2Fpbs.twimg.com%2Fmedia%2FGusLGxXXwAAVI3Y%3Fformat%3Djpg%26name%3Dlarge" 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%2Fpbs.twimg.com%2Fmedia%2FGusLGxXXwAAVI3Y%3Fformat%3Djpg%26name%3Dlarge" alt="Screenshot of tweet: " width="1898" height="908"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;what fine tuning prompts does to a chat history 😅 — &lt;a href="https://twitter.com/samitkapoorr/status/1939656501251232048" rel="noopener noreferrer"&gt;Samit Kapoor (@samitkapoorr)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Use XML tags
&lt;/h2&gt;

&lt;p&gt;If you're not using them, then using XML tags in your prompts can be a game-changer maybe.&lt;/p&gt;

&lt;p&gt;Think of XML tags as a way to give your prompts &lt;em&gt;structure&lt;/em&gt;. And as we know, better structure = better understanding for the AI. And prompt engineering is all about hitting that sweet spot where the AI consistently gives amazing results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;XML tags allow you to clearly define different sections or elements within your prompt. This can help the AI understand the relationships between different pieces of information and generate more coherent and relevant responses.&lt;/p&gt;

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

&lt;p&gt;Suppose you're building an AI wrapper that generates UI. You might start with a plain English description, but find it's not enough to enforce the desired behavior. Let's see how XML tags can level things up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version 0 (Plain English Description):&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;You are a helpful AI assistant that generates UI code. Be concise and use modern styling.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While this might give the AI a general idea, it's not very specific or enforceable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version 1 (Prompt with XML Tags):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;core_identity&amp;gt;&lt;/span&gt;
  You are a UI code generation assistant called "UI-Gen", designed to create clean, modern UI components based on user requests.
&lt;span class="nt"&gt;&amp;lt;/core_identity&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;general_guidelines&amp;gt;&lt;/span&gt;
  - ALWAYS generate code that is compatible with React.
  - ALWAYS use Tailwind CSS for styling.
  - NEVER include comments in the generated code.
  - ALWAYS be concise and efficient.
&lt;span class="nt"&gt;&amp;lt;/general_guidelines&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using XML tags, you're giving the AI a much more structured and enforceable set of instructions. You're clearly defining its core identity and providing specific guidelines for its behavior. This can lead to more consistent, predictable, and high-quality results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read other AI app's prompts
&lt;/h2&gt;

&lt;p&gt;If you're obsessed with an AI application and you love the outputs it gives, try reading the prompts that are powering their application.&lt;/p&gt;

&lt;p&gt;Now, of course, prompts are their super power, so they keep them a secret. But there's this github repo that you can checkout for yourself, it provides AI prompts to big names in AI like v0, cursor, lovable, cluely, cursor, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/tree/main" rel="noopener noreferrer"&gt;Link to GitHub repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, these may not provide you direct information on what to do to improve your prompts, but you can pick up a few insights just by reading through them. Apart from this, there are tons of open source AI projects, you can read their prompts as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Prompt Engineering Journey Starts Now
&lt;/h2&gt;

&lt;p&gt;So, there you have it: Prompt Engineering 101. We've covered a bunch of stuff, from using AI to write better prompts to A/B testing and even sneaking a peek at other AI apps' prompts.&lt;/p&gt;

&lt;p&gt;The key takeaway here is that prompt engineering is a skill, and like any skill, it takes practice. You gotta experiment, try new things, and see what works for you.&lt;/p&gt;




&lt;p&gt;Hi, I’m Samit, a software engineer and freelancer passionate about building real world projects. If you’re looking to collaborate or just want to say hi, check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;. Let’s connect&lt;/p&gt;

</description>
    </item>
    <item>
      <title>3 Simple Text Animations That You Can Build Using Framer Motion</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 28 Jun 2025 15:52:14 +0000</pubDate>
      <link>https://dev.to/samitkapoor/3-simple-text-animations-that-you-can-build-using-framer-motion-27h0</link>
      <guid>https://dev.to/samitkapoor/3-simple-text-animations-that-you-can-build-using-framer-motion-27h0</guid>
      <description>&lt;p&gt;Let's face it: animations make websites more interesting. They're great for grabbing attention and guiding people around the page. Almost all the AI SaaS websites landing pages will have them.&lt;/p&gt;

&lt;p&gt;The best part is that you don't have to be a wizard to implement them. In this article, I'm going to show you 3 simple text animations that you can build using &lt;a href="https://www.npmjs.com/package/framer-motion" rel="noopener noreferrer"&gt;framer motion&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Rainbow Text
&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%2Fgiwfdgfzt48gjmn947lg.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%2Fgiwfdgfzt48gjmn947lg.gif" alt="Rainbow Text" width="510" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think of it like this: instead of a single, solid color, your text has a gradient. And this gradient isn't static, it's constantly changing! The color at the end of the current gradient seamlessly flows into the beginning of the next, creating a continuous, mesmerizing rainbow effect.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Set up your component:&lt;/strong&gt; We'll start by creating a React component and adding some text. Instead of a fixed color, we'll give it an initial gradient.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;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;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cn&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;@/lib/utils&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;motion&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;framer-motion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RainbowTextProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RainbowText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;RainbowTextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;
      &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="na"&gt;backgroundImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;linear-gradient(90deg, #FF4D4D 0%, #FF944D 100%)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-transparent bg-clip-text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/motion.span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;What's going on here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We're importing &lt;code&gt;motion&lt;/code&gt; from &lt;code&gt;framer-motion&lt;/code&gt;. This is what allows us to animate the text.&lt;/li&gt;
&lt;li&gt;We're using &lt;code&gt;initial&lt;/code&gt; to set the starting gradient for the text.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;text-transparent bg-clip-text&lt;/code&gt; are tailwindcss classes that make the text transparent and clip the background to the text (so the gradient shows through). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important Note: If you have trouble understanding the above code, I'd recommend pausing here and checking out the basics of the &lt;a href="https://www.npmjs.com/package/framer-motion" rel="noopener noreferrer"&gt;Framer Motion&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create an array of gradients:&lt;/strong&gt; We need to make the gradient colors change over time, creating that flowing rainbow effect. To do this, we'll introduce a colors prop and create an array of linear gradients. We make sure the color at the end of the current gradient seamlessly flows into the beginning of the next.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RainbowText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FF4D4D&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;#FF944D&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;#FFC14D&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;#E8FF4D&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;#6DFF4D&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;#4DFFA1&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;#4DFFFF&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;#4DAAFF&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;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;RainbowTextProps&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;linearGradients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;linearGradients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`linear-gradient(90deg, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt; 0%, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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="s2"&gt; 100%)`&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;Bring it all together:&lt;/strong&gt; Now just pass on this &lt;code&gt;linearGradients&lt;/code&gt; array to &lt;code&gt;backgroundImage&lt;/code&gt; style in &lt;code&gt;animate&lt;/code&gt; prop of the span to complete the animation.&lt;/p&gt;

&lt;p&gt;Full implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;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;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cn&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;@/lib/utils&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;motion&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;framer-motion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RainbowTextProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RainbowText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FF4D4D&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;#FF944D&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;#FFC14D&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;#E8FF4D&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;#6DFF4D&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;#4DFFA1&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;#4DFFFF&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;#4DAAFF&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;#4D6DFF&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;#6D4DFF&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;#A14DFF&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;#D14DFF&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;#FF4DAA&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;#FF4D6D&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;#FF4D4D&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;#FF944D&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;RainbowTextProps&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;linearGradients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;linearGradients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`linear-gradient(90deg, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt; 0%, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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="s2"&gt; 100%)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;
      &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linearGradients&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linearGradients&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;linear&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-transparent bg-clip-text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/motion.span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;and Voila! there's your first text animation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wavy Text
&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%2Fjf59g93n78k2t14z0apw.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%2Fjf59g93n78k2t14z0apw.gif" alt="Wavy Text" width="510" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think of it like this: Every character in the text is animating on its own, and each character bounces up and down but they don't all start at the same time, there's a delay to when they start bouncing which creates a wave.&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%2Ffvaayd56qp7msai59e8f.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%2Ffvaayd56qp7msai59e8f.gif" alt="Failed wave" width="220" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Setup your component:&lt;/strong&gt; Start by initializing the component, defining the necessary props, and rendering the text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WavyTextProps&lt;/span&gt; &lt;span class="o"&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;className&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WavyText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;WavyTextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`flex flex-wrap overflow-visible p-4 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;className&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Make each character an individual element:&lt;/strong&gt; Since I told you each character is animating on its own, we have to break the text and render each character separately like so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`flex flex-wrap overflow-visible p-4 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;className&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="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;u00A0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;char&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;/motion.span&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;      &lt;span class="p"&gt;})}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add bouncing properties to each character and bring it all together&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Full implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;motion&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;framer-motion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WavyTextProps&lt;/span&gt; &lt;span class="o"&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;className&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WavyText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;WavyTextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`flex flex-wrap overflow-visible p-4 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;className&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="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="nx"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spring&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;stiffness&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="na"&gt;damping&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;repeatType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reverse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;}}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;u00A0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;char&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;/motion.span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;What's going on here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We set the initial ‎&lt;code&gt;y&lt;/code&gt; value to -15, so each character starts 15 pixels above its resting position.&lt;/li&gt;
&lt;li&gt;The ‎&lt;code&gt;animate&lt;/code&gt; prop moves each character between 0 and -15 pixels, creating the bouncing motion.&lt;/li&gt;
&lt;li&gt;The spring transition adds realistic physics, making each bounce feel natural.&lt;/li&gt;
&lt;li&gt;The delay, multiplied by the character’s index, staggers the animation and creates the wave effect.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Blur Text
&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%2F7197y2hw6meatwtv8x00.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%2F7197y2hw6meatwtv8x00.gif" alt="Blur Text" width="510" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think of it like this: Each character starts out slightly blurred and shifted downward from its final position. As the animation plays, each character sharpens into focus and smoothly rises to its resting place.&lt;/p&gt;

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

&lt;p&gt;So, the first two steps are actually the same as the Wavy Text, let's build from there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;motion&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;framer-motion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BlurTextProps&lt;/span&gt; &lt;span class="o"&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;className&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlurText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;BlurTextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`flex flex-wrap overflow-visible &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;className&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="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline-block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;u00A0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;char&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;/motion.span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;BlurText&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;Now, let’s add the animation:&lt;/strong&gt; each character will start blurred and slightly lower than its final position, then animate into focus and rise up to its resting place. We’ll also stagger the animation for each character to create a smooth, sequential effect.&lt;/p&gt;

&lt;p&gt;Full implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;motion&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;framer-motion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BlurTextProps&lt;/span&gt; &lt;span class="o"&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;className&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlurText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;BlurTextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`flex flex-wrap overflow-visible &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;className&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="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;
          &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blur(10px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
          &lt;span class="nx"&gt;whileInView&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blur(0px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
          &lt;span class="nx"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
            &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;backOut&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="p"&gt;}}&lt;/span&gt;
          &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline-block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;u00A0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;char&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;/motion.span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;What's going on here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each character starts with a ‎&lt;code&gt;y&lt;/code&gt; value of 10 (10 pixels below its final position) and a heavy blur applied.&lt;/li&gt;
&lt;li&gt;The ‎&lt;code&gt;whileInView&lt;/code&gt; prop animates each character upward to its resting position and removes the blur, making the text crisp and clear.&lt;/li&gt;
&lt;li&gt;The transition uses a small duration and a staggered delay based on the character’s index, so each letter animates one after another, creating a smooth reveal effect.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why do we use the &lt;code&gt;whileInView&lt;/code&gt; prop here, but the &lt;code&gt;animate&lt;/code&gt; prop in Wavy Text?
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;animate&lt;/code&gt; prop triggers the animation immediately when the component renders, regardless of whether the text is visible on the screen. In contrast, the &lt;code&gt;whileInView&lt;/code&gt; prop starts the animation only when the text actually comes into the user's viewport. For the blur text effect, using &lt;code&gt;animate&lt;/code&gt; could cause the animation to play off-screen, so users might miss it entirely. By using &lt;code&gt;whileInView&lt;/code&gt;, we ensure the animation runs at the right moment when the user can actually see it.&lt;/p&gt;

&lt;p&gt;If you enjoyed these animations and want to discover even more, check out my open source animated library, &lt;a href="https://stackbits.dev" rel="noopener noreferrer"&gt;stackbits.dev&lt;/a&gt;, for a collection of ready-to-use animation components!&lt;/p&gt;




&lt;p&gt;Hi, I’m Samit, a software engineer and freelancer passionate about building real world projects. If you’re looking to collaborate or just want to say hi, check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;. Let’s connect!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>motion</category>
    </item>
    <item>
      <title>How Bloom Filters Help Tech Giants Manage Massive Caches</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 21 Jun 2025 10:59:37 +0000</pubDate>
      <link>https://dev.to/samitkapoor/how-bloom-filters-help-tech-giants-manage-massive-caches-5854</link>
      <guid>https://dev.to/samitkapoor/how-bloom-filters-help-tech-giants-manage-massive-caches-5854</guid>
      <description>&lt;p&gt;Ever wondered how tech giants like Facebook, Google, and Akamai, manage their massive caches? &lt;/p&gt;

&lt;p&gt;With millions of users and countless searches, how do they figure out what to store in their cache and what not to store in their cache? &lt;/p&gt;

&lt;p&gt;How do they quickly find out if an item is a frequently searched item or not?&lt;/p&gt;

&lt;p&gt;This is where bloom filters come into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Bloom filters?
&lt;/h2&gt;

&lt;p&gt;According to the definition, "A Bloom filter is a space-efficient probabilistic data structure used to test set membership."&lt;/p&gt;

&lt;p&gt;In layman's terms, a Bloom filter is a clever data structure that allows you to check if an item is present or not present in a set.&lt;/p&gt;

&lt;p&gt;Bloom Filters use several independent hash functions and an array of fixed size containing only 0s and 1s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;Let's take an example to understand how it works.&lt;/p&gt;

&lt;p&gt;For this example, let's assume that there are 3 hash functions and the length of the bit array is 10.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Suppose a user comes on Facebook and searches for a word, let's say "Party".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now Facebook first needs to figure out if search results for the word "Party" are in their cache or not. So Facebook consults its Bloom filter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The word "Party" is passed through all the independent hash functions resulting in indices in the bit array.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h1("Party") = 2
h2("Party") = 5
h3("Party") = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next we examine the bits at these positions in the array. Suppose our bit array currently looks like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;array: [0, 1, 1, 0, 1, 0, 1, 0, 0, 0]
index:  0, 1, 2, 3, 4, 5, 6, 7, 8, 9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bits at 2, 5, 1 are 1, 0, 1 respectively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Since not all the bits are set (bit at index 5 is 0), we can be certain the "Party" is not present in cache.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If all the bits were set to 1, it would indicate that "Party" might be present in the cache.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bloom filters doesn't guarantee that the item will be present in the data set, but it guarantees that the item will not be present in the data set.&lt;/p&gt;

&lt;p&gt;The example above demonstrates how to check if an item is present in the cache, but how can we determine whether a searched item is frequently requested?&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do Bloom Filters Help Manage and Update the Cache?
&lt;/h2&gt;

&lt;p&gt;Let’s build on our earlier example:&lt;/p&gt;

&lt;p&gt;Suppose the word "Party" was not found in the cache because the bit at index 5 was unset. When we set this bit, the next search for "Party" will indicate a possible presence in the cache, allowing for a quick lookup.&lt;/p&gt;

&lt;p&gt;However, when millions of users are making thousands of requests per second, this approach runs into a problem. If we set bits for every search, the Bloom filter’s bit array will quickly fill up with 1s, reducing its effectiveness and causing frequent false positives.&lt;/p&gt;

&lt;p&gt;To address this, systems often use multiple Bloom filters (or layers of bit arrays). Here’s how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bloom filter 1: [0, 1, 1, 0, 1, 0, 1, 0, 0, 0]
Bloom filter 2: [0, 1, 0, 1, 1, 0, 1, 1, 0, 0]
.
.
.
Bloom filter n: [1, 0, 0, 0, 1, 0, 1, 1, 0, 1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Each time "Party" is searched, we update a different layer or bit array.&lt;/li&gt;
&lt;li&gt;For example, "Party" might appear present in the first Bloom filter, but absent in the second. This indicates it has been searched before, but not often enough to be considered “frequently searched.”&lt;/li&gt;
&lt;li&gt;Only when "Party" is found to be present in all layers do we treat it as a frequently accessed item and consider storing or updating it in the cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This layered approach helps distinguish between items that are searched occasionally and those that are truly popular, ensuring that the cache is used efficiently and only for items with sustained demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  False Positives
&lt;/h2&gt;

&lt;p&gt;A false positive occurs when the Bloom filter suggests that an item might be present in the cache, but in reality, it isn’t. As discussed earlier, Bloom filters doesn't guarantee that the item will be present in the data set, but it guarantees that the item will not be present in the data set.&lt;/p&gt;

&lt;p&gt;This happens because multiple different items can set the same bits in the bit array. So, when you query for an item and all its corresponding bits are set to 1, it’s possible those bits were set by other items, not the one you’re searching for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this acceptable?
&lt;/h2&gt;

&lt;p&gt;This tradeoff is fundamental to Bloom filters. In many system design scenarios, it’s acceptable to occasionally perform an unnecessary cache lookup (due to a false positive), as this is far less costly than searching the entire database for every request. The Bloom filter helps minimize expensive database operations, even if it sometimes leads to extra cache lookups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Bloom filters might seem simple, but their ability to deliver fast, space efficient, and probabilistic checks makes them incredibly powerful for large scale systems. From reducing unnecessary database lookups to optimizing cache usage, they quietly power some of the biggest tech infrastructures behind the scenes.&lt;/p&gt;




&lt;p&gt;Hi, I’m Samit, a software developer and freelancer passionate about building real world projects. If you’re looking to collaborate or just want to say hi, check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;. Let’s connect!&lt;/p&gt;

</description>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Understanding Query Cost in SQL</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 14 Jun 2025 11:23:15 +0000</pubDate>
      <link>https://dev.to/samitkapoor/understanding-query-cost-in-sql-3emh</link>
      <guid>https://dev.to/samitkapoor/understanding-query-cost-in-sql-3emh</guid>
      <description>&lt;p&gt;Recently, I've been delving into system design, aiming to uncover what happens beneath the surface—how systems operate, where bottlenecks occur, and how we can optimize for speed, reliability, and security.&lt;/p&gt;

&lt;p&gt;Every SQL query comes with a performance cost. Some operations are lightweight, while others can significantly slow down your application. Because each database query can directly affect your server's responsiveness, it's crucial to understand what makes certain queries more expensive than others.&lt;/p&gt;

&lt;p&gt;In this article, we'll break down the factors that contribute to SQL query costs and explore how you can make smarter choices to keep your systems fast and efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  What determines a Query cost?
&lt;/h2&gt;

&lt;p&gt;When you run a SQL query, several factors work together to determine how “expensive” that operation is for your database. Query cost refers to the resources like &lt;code&gt;CPU&lt;/code&gt;, &lt;code&gt;memory&lt;/code&gt;, &lt;code&gt;disk I/O&lt;/code&gt;, and &lt;code&gt;network bandwidth&lt;/code&gt;—things that your database engine must use to execute a given command. Understanding these factors can help you write more efficient queries and design better systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Data Volume:&lt;/strong&gt; The more data a query has to scan or process, the higher the cost. For example, searching through millions of rows without an index will take much longer than querying a small, well-indexed table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Index Usage:&lt;/strong&gt; Indexes can dramatically speed up read operations by letting the database find data without scanning every row. However, maintaining indexes also adds overhead to write operations like &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, and &lt;code&gt;DELETE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Query Complexity:&lt;/strong&gt; Complex queries with multiple &lt;code&gt;JOIN&lt;/code&gt;s, subqueries, aggregations, or sorting operations require more processing power and memory. The more logic the database has to execute, the higher the cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Locking and Concurrency:&lt;/strong&gt; When multiple queries try to access or modify the same data simultaneously, the database may need to lock certain rows or tables. This can increase latency and resource usage, especially for write-heavy workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Hardware and Configuration:&lt;/strong&gt; The underlying hardware (&lt;code&gt;CPU&lt;/code&gt;, &lt;code&gt;RAM&lt;/code&gt;, disk speed) and database configuration (buffer sizes, cache settings) also play a role in how efficiently queries are executed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Network Overhead:&lt;/strong&gt; If your database and application servers are on different machines, network latency and bandwidth can add to the overall query cost when transferring large result sets.&lt;/p&gt;

&lt;p&gt;In short, query cost is a combination of how much data is touched, how the data is accessed, and how complex the query logic is, all influenced by the environment in which the database runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's look at SQL Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SELECT&lt;/code&gt; Command
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;SELECT&lt;/code&gt; command allows you to retrieve data from one or more tables in your database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens under the hood?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When you execute a &lt;code&gt;SELECT&lt;/code&gt; query, the database engine parses your request and determines the most efficient way to fetch the data. If your query is well-optimized and uses indexes, the engine can quickly locate the relevant rows. Otherwise, it may need to perform a full table scan, reading every row to find matches—a much more resource-intensive process. The &lt;a href="https://planetscale.com/blog/what-is-a-query-planner" rel="noopener noreferrer"&gt;&lt;code&gt;query planner&lt;/code&gt;&lt;/a&gt; also decides the order of operations, how joins are executed, and whether to use temporary storage for sorting or aggregations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expensive patterns:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full table scans:&lt;/strong&gt; Occur when there’s no usable index for the &lt;code&gt;WHERE&lt;/code&gt; clause, forcing the database to read every row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex joins:&lt;/strong&gt; Joining large tables without proper indexing can lead to massive intermediate result sets and slow performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subqueries and nested &lt;code&gt;SELECT&lt;/code&gt;s:&lt;/strong&gt; These can multiply the amount of data processed, especially if not correlated efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ORDER BY&lt;/code&gt; and &lt;code&gt;GROUP BY&lt;/code&gt; on large datasets:&lt;/strong&gt; Sorting and grouping require additional memory and processing, which can become costly at scale.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Suppose you want to find all users with a specific email domain:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%@example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If there’s no index on the &lt;code&gt;email&lt;/code&gt; column, the database must scan every user row to check the condition, making this query expensive for large tables. &lt;/p&gt;

&lt;p&gt;Adding an index on the &lt;code&gt;email&lt;/code&gt; column can significantly reduce the cost, allowing the database to quickly locate matching rows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now suppose you want to list all orders along with customer names for customers from a specific city:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'New York'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If there are no indexes on &lt;code&gt;customers.city&lt;/code&gt; or &lt;code&gt;orders.customer_id&lt;/code&gt;, the database must scan both tables and compare every possible pair to find matches. This results in a costly operation, especially as the tables grow larger. Additionally, if &lt;code&gt;orders&lt;/code&gt; and &lt;code&gt;customers&lt;/code&gt; are both large, the intermediate result set can consume significant memory and processing time. &lt;/p&gt;

&lt;p&gt;Adding an index on &lt;code&gt;customers.city&lt;/code&gt; allows the database to quickly filter relevant customers. Similarly, indexing &lt;code&gt;orders.customer_id&lt;/code&gt; speeds up the join operation. With proper indexes, the database can efficiently match only the necessary rows, dramatically reducing the query cost.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;INSERT&lt;/code&gt; Command
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;INSERT&lt;/code&gt; statement is used to add new rows of data into a table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens under the hood?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When you execute an &lt;code&gt;INSERT&lt;/code&gt;, the database engine first checks if the data types and constraints (like &lt;code&gt;NOT NULL&lt;/code&gt;, &lt;code&gt;UNIQUE&lt;/code&gt;, or &lt;code&gt;FOREIGN KEY&lt;/code&gt;) are satisfied. If the table has any indexes, the engine updates them to include the new data. For tables with triggers or default values, those are also processed during the operation. Each insert is logged for durability and potential rollback, which can add overhead, especially in systems with heavy write activity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expensive patterns:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bulk inserts without batching:&lt;/strong&gt; Inserting a massive number of rows in a single transaction can overwhelm memory and transaction logs, causing slowdowns or even failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tables with many indexes:&lt;/strong&gt; Every index must be updated when new data is inserted, which increases the time and resources required for the operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraint checks:&lt;/strong&gt; Validating foreign keys or unique constraints for each row can become costly, particularly in large or highly related tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a single new user to the &lt;code&gt;users&lt;/code&gt; table:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'alice@example.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'New York'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This operation is straightforward and typically fast, especially if the table has only a few indexes and constraints.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now suppose you want to add multiple orders for a customer, and each order must reference an existing customer in the &lt;code&gt;customers&lt;/code&gt; table (enforced by a foreign key constraint):
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; 
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2025-06-14'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2025-06-15'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2025-06-16'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, the database must check that &lt;code&gt;customer_id&lt;/code&gt; 101 exists in the &lt;code&gt;customers&lt;/code&gt; table for each row and update any relevant indexes. If the &lt;code&gt;orders&lt;/code&gt; table has several indexes or triggers, or if you’re inserting thousands of rows at once, the operation can become much more resource-intensive and slower. &lt;/p&gt;

&lt;p&gt;Using transactions and batching can help manage the cost of such complex inserts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Batching Example:&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;batchInsertOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;batchSize&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;batchSize&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;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;batchSize&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;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="nx"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// For each order, push the values and build the parameterized query&lt;/span&gt;
      &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`($&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&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="s2"&gt;, $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;order&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="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
      INSERT INTO orders (customer_id, order_date, total)
      VALUES &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;
    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BEGIN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COMMIT&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;h3&gt;
  
  
  &lt;code&gt;UPDATE&lt;/code&gt; Command
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;UPDATE&lt;/code&gt; statement allows you to modify existing records in a table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens under the hood?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When an &lt;code&gt;UPDATE&lt;/code&gt; command runs, the database engine locates the rows that match your &lt;code&gt;WHERE&lt;/code&gt; clause, locks them to prevent conflicting changes, checks for constraint violations, applies the new values, and updates any relevant indexes. Each change is logged for durability and possible rollback, which adds overhead, especially with large or complex updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expensive patterns:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Updating large numbers of rows:&lt;/strong&gt; Running an &lt;code&gt;UPDATE&lt;/code&gt; without a selective &lt;code&gt;WHERE&lt;/code&gt; clause can affect every row in the table, leading to significant I/O and locking overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Updating indexed columns:&lt;/strong&gt; When you modify a column that’s part of one or more indexes, the database must update those indexes for each changed row, increasing the operation’s cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex &lt;code&gt;WHERE&lt;/code&gt; conditions:&lt;/strong&gt; If your &lt;code&gt;WHERE&lt;/code&gt; clause uses non-indexed columns or involves complex logic, the database may need to scan the entire table to identify matching rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cascading updates and triggers:&lt;/strong&gt; If your table uses foreign keys with cascading updates or has triggers that fire on update, each affected row can cause additional operations, further increasing cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Suppose you want to update the &lt;code&gt;city&lt;/code&gt; for a single user based on their &lt;code&gt;email&lt;/code&gt; address:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'San Francisco'&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'alice@example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there’s an index on the &lt;code&gt;email&lt;/code&gt; column, the database can quickly find and update the relevant row. This is a lightweight operation with minimal impact on performance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, imagine you need to update the &lt;code&gt;status&lt;/code&gt; of all orders placed before a certain date and with a total greater than &lt;code&gt;$500&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'archived'&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;order_date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="s1"&gt;'2025-01-01'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query may affect many rows, especially in a large table. If the &lt;code&gt;order_date&lt;/code&gt; or &lt;code&gt;total&lt;/code&gt; columns aren’t indexed, the database must scan the entire table to find matches, making the operation much more expensive. Additionally, if the &lt;code&gt;status&lt;/code&gt; column is indexed, the index must be updated for every changed row, adding further cost.&lt;/p&gt;

&lt;p&gt;To make this update more efficient, you can add indexes on the columns used in the &lt;code&gt;WHERE&lt;/code&gt; clause—&lt;code&gt;order_date&lt;/code&gt; and &lt;code&gt;total&lt;/code&gt;. This allows the database to quickly locate only the relevant rows instead of scanning the entire table. For very large tables, consider batching the updates to reduce locking and transaction log pressure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips for optimizing Query Cost
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Indexes Wisely:&lt;/strong&gt; Add indexes to columns that are frequently used in &lt;code&gt;WHERE&lt;/code&gt; clauses, &lt;code&gt;JOIN&lt;/code&gt; conditions, and &lt;code&gt;ORDER BY&lt;/code&gt; statements. However, avoid over-indexing, as each index adds overhead to &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, and &lt;code&gt;DELETE&lt;/code&gt; operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write Selective Queries:&lt;/strong&gt; Always aim to filter data as much as possible in your queries. Use specific &lt;code&gt;WHERE&lt;/code&gt; clauses to limit the number of rows processed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid &lt;code&gt;SELECT *&lt;/code&gt;:&lt;/strong&gt; Only retrieve the columns you need, rather than selecting all columns from a table. This reduces the amount of data transferred and processed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Batch Write Operations:&lt;/strong&gt; For large &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, or &lt;code&gt;DELETE&lt;/code&gt; operations, process data in smaller batches to reduce locking, transaction log usage, and potential timeouts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep Transactions Short:&lt;/strong&gt; Long-running transactions can hold locks and block other operations. Commit your changes as soon as possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimize Joins:&lt;/strong&gt; Use appropriate join types and make sure joined columns are indexed. Avoid joining large tables without filters or indexes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Proper Data Types:&lt;/strong&gt; Choose the most efficient data types for your columns to minimize storage and speed up processing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Hi, I’m Samit, a software developer and freelancer passionate about building real world projects. If you’re looking to collaborate or just want to say hi, check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;. Let’s connect!&lt;/p&gt;

</description>
      <category>sql</category>
      <category>database</category>
    </item>
    <item>
      <title>--legacy-peer-deps vs --force: Understanding npm's conflict resolvers</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 07 Jun 2025 13:42:56 +0000</pubDate>
      <link>https://dev.to/samitkapoor/-legacy-peer-deps-vs-force-understanding-npms-conflict-resolvers-3h8m</link>
      <guid>https://dev.to/samitkapoor/-legacy-peer-deps-vs-force-understanding-npms-conflict-resolvers-3h8m</guid>
      <description>&lt;p&gt;If you've ever been stuck while installing a package in a Node.js project and found yourself using &lt;code&gt;--legacy-peer-deps&lt;/code&gt; or &lt;code&gt;--force&lt;/code&gt; without really knowing what they do then, you're not alone.&lt;/p&gt;

&lt;p&gt;These flags often appear when there are conflicts in &lt;code&gt;peerDependencies&lt;/code&gt;, but what exactly do they mean, and which one should you use?&lt;/p&gt;

&lt;p&gt;Let’s break it down. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Dependency Conflicts in npm
&lt;/h2&gt;

&lt;p&gt;Dependency conflicts happen when different packages in your project require &lt;strong&gt;incompatible versions of the same dependency&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
For example, one package might need &lt;code&gt;react@17&lt;/code&gt; while another expects &lt;code&gt;react@18&lt;/code&gt;. Since there's no clean way to install multiple versions of the same package simultaneously, npm throws an error.&lt;/p&gt;

&lt;p&gt;These conflicts usually indicate that your project's dependency tree is either fragile, outdated, or includes libraries that haven’t been updated to support newer versions of their peers.&lt;/p&gt;

&lt;p&gt;To bypass these errors, npm provides two commonly used flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--legacy-peer-deps&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--force&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's understand them one by one.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;--legacy-peer-deps&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When you use &lt;code&gt;--legacy-peer-deps&lt;/code&gt;, here's what it means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ignore the peer dependency conflicts.&lt;/li&gt;
&lt;li&gt;Doesn't attempt to automatically install peer dependency.&lt;/li&gt;
&lt;li&gt;Avoid breaking the dependency tree.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;You're using older packages that haven't updated yet.&lt;/li&gt;
&lt;li&gt;You want to avoid forcing incompatible versions together.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i some-package --legacy-peer-deps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;--force&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When you use &lt;code&gt;--force&lt;/code&gt;, here's what it means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forcefully install the package even if the tree is already broken.&lt;/li&gt;
&lt;li&gt;Potentially lead to unstable project.&lt;/li&gt;
&lt;li&gt;Overrides dependency conflicts, peer mismatches, etc.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;You're just testing out things quickly.&lt;/li&gt;
&lt;li&gt;You know what you're doing and can resolve conflicts later if required.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i some-package --force
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Which one should you choose?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;--legacy-peer-deps&lt;/code&gt; when you're facing peer dependency issues with older libraries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid &lt;code&gt;--force&lt;/code&gt; unless you're experimenting or absolutely sure of what you're doing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Hi, I’m Samit, a software developer and freelancer passionate about building real world projects. If you’re looking to collaborate or just want to say hi, check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;. Let’s connect!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding React's Declarative UI Through a Copy Button Example</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 31 May 2025 11:58:56 +0000</pubDate>
      <link>https://dev.to/samitkapoor/understanding-reacts-declarative-ui-through-a-copy-button-example-499c</link>
      <guid>https://dev.to/samitkapoor/understanding-reacts-declarative-ui-through-a-copy-button-example-499c</guid>
      <description>&lt;p&gt;I was building a simple Copy button. The kind that copies some text to the clipboard and briefly shows a “Copied!” message for 1 second before reverting to its original label.&lt;/p&gt;

&lt;p&gt;I already knew how to implement it the “React way” using &lt;code&gt;useState&lt;/code&gt; to manage the button’s text. But out of curiosity, I decided to try a more direct approach using vanilla JavaScript’s DOM manipulation by changing innerText manually.&lt;/p&gt;

&lt;p&gt;That small decision led me down an unexpected path and helped me better understand React’s declarative nature. Let’s explore what happened and why it’s an important lesson for anyone working with React.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Imperative Attempt
&lt;/h2&gt;

&lt;p&gt;Here's what I tried doing. Instead of relying on React state, I tried change the value of &lt;code&gt;innerText&lt;/code&gt; inside the &lt;code&gt;onClick&lt;/code&gt; handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
  &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&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;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Copied!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&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;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&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;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&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;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This seems like it should work. When the button is clicked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The text gets copied to the clipboard.&lt;/li&gt;
&lt;li&gt;I change the &lt;code&gt;innerText&lt;/code&gt; value of the button to 'Copied!'.&lt;/li&gt;
&lt;li&gt;After a second the &lt;code&gt;innerText&lt;/code&gt; value of the button is changed back to what it was.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in reality button's &lt;code&gt;innerText&lt;/code&gt; value changed to 'Copied!' but it never changed back to &lt;code&gt;text&lt;/code&gt; value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it doesn't work?
&lt;/h2&gt;

&lt;p&gt;It didn't work simply because React didn't know that I manipulated the DOM.&lt;/p&gt;

&lt;p&gt;The issue lies in React's declarative rendering model. The UI is a reflection of component's state and props. When you write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&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;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're telling React "The content of this button should always be whatever the value of &lt;code&gt;text&lt;/code&gt; is".&lt;/p&gt;

&lt;p&gt;React uses virtual DOM to keep track of what UI should look like and compare it with the real DOM to figure out what needs to be changed.&lt;/p&gt;

&lt;p&gt;So when I tried to change the value of &lt;code&gt;innerText&lt;/code&gt; back to &lt;code&gt;text&lt;/code&gt; after 1 second... it failed because React had already re-rendered that component in between due to stricter mode in development. By the time the timeout ran DOM node has already been replaced and that's why it gets stucked to 'Copied!' only.&lt;/p&gt;

&lt;p&gt;Vanilla JS DOM manipulation in React is an anti pattern and this is why it isn't advised, they may get silently ignored or break when DOM is rebuilt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;useState&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of manually updating the DOM, we use &lt;code&gt;useState&lt;/code&gt; to register updates.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CopyButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;displayText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDisplayText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&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;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setDisplayText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Copied!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setDisplayText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;displayText&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;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&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;CopyButton&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The button's text is controlled by &lt;code&gt;displayText&lt;/code&gt;, a React state variable. When the button is clicked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We write to the clipboard.&lt;/li&gt;
&lt;li&gt;We update the state to 'Copied!', triggering a React re-render.&lt;/li&gt;
&lt;li&gt;After 1 second, we reset the state back to the original text, triggering another re-render.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;React uses the Virtual DOM to efficiently update the UI with each state change.&lt;/p&gt;

&lt;p&gt;Since React is in charge of rendering, the UI always stays in sync with the component’s logic, no surprises, no manual &lt;code&gt;innerText&lt;/code&gt; issues, and no bugs due to stale DOM nodes.&lt;/p&gt;




&lt;p&gt;Hi, I'm Samit. A Software Developer and a freelancer who’s always on the lookout for exciting, real world projects to build and contribute to. I love hearing from people, whether it’s to collaborate, share ideas, or work together.&lt;/p&gt;

&lt;p&gt;If you're looking to hire a passionate developer or even if you just want to say hi, feel free to check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt; and reach out. I'd love to connect!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Streaming Downloads from S3 in React and Node.js (The Right Way)</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 24 May 2025 10:20:52 +0000</pubDate>
      <link>https://dev.to/samitkapoor/streaming-downloads-from-s3-in-react-and-nodejs-the-right-way-3kce</link>
      <guid>https://dev.to/samitkapoor/streaming-downloads-from-s3-in-react-and-nodejs-the-right-way-3kce</guid>
      <description>&lt;p&gt;Recently, I was asked to add a button on a frontend dashboard that would allow users to bulk download Excel reports for multiple users. Having never implemented this before, my initial approach was to download all the files from S3 on the backend, convert them to base64 strings, send them as an array to the frontend, and then convert those base64 strings back into files for download on the user's machine.&lt;/p&gt;

&lt;p&gt;It seemed simple enough but is not at all scalable.&lt;/p&gt;

&lt;p&gt;Think about it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What if there are thousands of users whose reports need to be downloaded?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What if each report is large in size?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What if multiple users initiate the download at the same time?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach would quickly become a bottleneck, putting unnecessary load on the backend server, increasing memory usage, and ultimately hurting performance.&lt;/p&gt;

&lt;p&gt;That’s when I discovered a better way, streaming file downloads directly from S3 to the frontend.&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk you through how to implement this properly using Node.js on the backend and React.js on the frontend, so users can download large files efficiently without choking your server.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does It Work?
&lt;/h2&gt;

&lt;p&gt;This is the theory part, feel free to skip ahead to the implementation if you're already familiar with how streaming works.&lt;/p&gt;

&lt;p&gt;Here’s a simplified overview of the process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user clicks a button on the frontend to initiate a bulk download.&lt;/li&gt;
&lt;li&gt;A request is sent from the frontend to the backend API endpoint.&lt;/li&gt;
&lt;li&gt;The backend connects to AWS S3 and requests the file(s), creating a &lt;code&gt;ReadableStream&lt;/code&gt; from the S3 response.&lt;/li&gt;
&lt;li&gt;This stream is piped directly to the HTTP response, which sends the file data in chunks to the frontend as it arrives.&lt;/li&gt;
&lt;li&gt;On the frontend, the browser receives this data and converts it into a downloadable file, without needing to load the entire file into memory.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Is This Better?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced Server Load:&lt;/strong&gt; The backend doesn't store or buffer the entire file. It simply acts as a proxy, streaming the data directly from S3 to the client. This means far less memory and CPU usage on your server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handles Large Files Gracefully:&lt;/strong&gt; Whether you're downloading a 1MB file or a 1GB report, the process is the same, data flows in chunks and doesn't overwhelm the server. The only limiting factor is the user's network speed and local storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scales with Multiple Users:&lt;/strong&gt; Since each user's system handles their own download, the backend doesn’t need to manage multiple large file buffers simultaneously. The load is distributed naturally across client machines.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Backend Implementation
&lt;/h2&gt;

&lt;p&gt;On the backend, we create a ZIP archive of all the requested files from S3 and stream it directly in the response without storing anything temporarily on the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;archiver&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;archiver&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;getAwsClient&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;./aws.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Add your own import&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;downloadFiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;files&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;body&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;AWS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getAwsClient&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;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;S3&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;setHeader&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/zip&lt;/span&gt;&lt;span class="dl"&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;setHeader&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-Disposition&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;attachment; filename=files.zip&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;archive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;archiver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zip&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;zlib&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// Best compression&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;archive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&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;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;Archive error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Internal Server Error&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;archive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&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="c1"&gt;// Connect zip stream to the HTTP response&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&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;s3Stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getObject&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;Bucket&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;S3_BUCKET_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Make sure this is defined&lt;/span&gt;
        &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createReadStream&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;archive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s3Stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;archive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Triggers the streaming download&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We use &lt;code&gt;archiver&lt;/code&gt; to zip files on the fly.&lt;/li&gt;
&lt;li&gt;Files are streamed from &lt;strong&gt;S3 directly&lt;/strong&gt;, not buffered or saved temporarily.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frontend Implementation
&lt;/h2&gt;

&lt;p&gt;On the frontend, we send a request to the backend to start the bulk download. The backend streams the zipped file, which we receive as a Blob and trigger the browser to download it directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;request&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;./axios/request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Replace with your actual axios instance&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;downloadAllReports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Send POST request to initiate bulk download&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&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;/bulk-download&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;files&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;file1.pdf&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;file2.jpg&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;// List your files here&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;responseType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Important: tells axios to handle response as Blob&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a Blob from the response data&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Blob&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/zip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a temporary URL for the Blob object&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a hidden anchor element and trigger the download&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;report.zip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Filename for the downloaded file&lt;/span&gt;
    &lt;span class="nb"&gt;document&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="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Clean up by removing the anchor and revoking the object URL&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revokeObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Download failed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&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;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Streaming file downloads is a powerful technique to handle large or multiple files efficiently without overloading your backend server. By leveraging streams, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce server memory and CPU usage
&lt;/li&gt;
&lt;li&gt;Enable scalable downloads for many users simultaneously
&lt;/li&gt;
&lt;li&gt;Provide a smooth download experience even for large files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re building any app that involves bulk file downloads or large reports, consider using streaming to keep your system fast and scalable.&lt;/p&gt;




&lt;p&gt;Hi, I'm Samit. A Software Developer and a freelancer who’s always on the lookout for exciting, real world projects to build and contribute to. I love hearing from people, whether it’s to collaborate, share ideas, or work together.&lt;/p&gt;

&lt;p&gt;If you're looking to hire a passionate developer or even if you just want to say hi, feel free to check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt; and reach out. I'd love to connect!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>node</category>
      <category>s3</category>
    </item>
    <item>
      <title>How to Customize Tailwind CSS in Next.js 15 Without tailwind.config.js?</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sun, 18 May 2025 09:31:27 +0000</pubDate>
      <link>https://dev.to/samitkapoor/how-to-customize-tailwind-css-in-nextjs-15-without-tailwindconfigjs-26e4</link>
      <guid>https://dev.to/samitkapoor/how-to-customize-tailwind-css-in-nextjs-15-without-tailwindconfigjs-26e4</guid>
      <description>&lt;p&gt;Tailwind CSS v4 and Next.js 15 introduce a new way of customizing your design tokens and themes, without even touching a &lt;code&gt;tailwind.config.js&lt;/code&gt; file. If you’re used to defining your custom colors, fonts, and spacing inside the config file, this new &lt;code&gt;@theme inline&lt;/code&gt; approach might feel unfamiliar at first but it’s incredibly powerful.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through How to customize your Tailwind setup using &lt;code&gt;@theme inline&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Why &lt;code&gt;tailwind.config.js&lt;/code&gt; Is Optional in Next.js 15
&lt;/h2&gt;

&lt;p&gt;Starting with &lt;strong&gt;Tailwind CSS v4&lt;/strong&gt;, the team is moving toward a &lt;strong&gt;zero-config setup&lt;/strong&gt;. When you're working in a modern framework like &lt;strong&gt;Next.js 15&lt;/strong&gt;, Tailwind automatically configures itself via PostCSS and &lt;code&gt;globals.css&lt;/code&gt;, meaning you don’t need a &lt;code&gt;tailwind.config.js&lt;/code&gt; file unless you're doing something advanced like adding plugins.&lt;/p&gt;

&lt;p&gt;With the new &lt;code&gt;@theme&lt;/code&gt; directive, you can define custom design tokens inline in your CSS file (usually &lt;code&gt;globals.css&lt;/code&gt;), which Tailwind will pick up and compile at build time.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✍️ How to Use &lt;code&gt;@theme inline&lt;/code&gt; in Next.js 15
&lt;/h2&gt;

&lt;p&gt;Here’s how you can define custom colors, fonts, and other variables in &lt;code&gt;globals.css&lt;/code&gt; using &lt;code&gt;@theme inline&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* app/globals.css */&lt;/span&gt;

&lt;span class="k"&gt;@theme&lt;/span&gt; &lt;span class="nb"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--color-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--color-primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#66BB6A&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#d90000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--font-chillax&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Chillax-Variable'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can use these values in your utility classes just like built-in tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-primary text-foreground font-chillax"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Hello from your custom Tailwind setup!
&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are some of the available theme variables that you can use!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Namespace&lt;/th&gt;
&lt;th&gt;Utility Classes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--color-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Color utilities like &lt;code&gt;bg-red-500&lt;/code&gt;, &lt;code&gt;text-sky-300&lt;/code&gt;, and many more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--font-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Font family utilities like &lt;code&gt;font-sans&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--text-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Font size utilities like &lt;code&gt;text-xl&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--breakpoint-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Responsive breakpoint variants like &lt;code&gt;sm:*&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--spacing-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spacing and sizing utilities like &lt;code&gt;px-4&lt;/code&gt;, &lt;code&gt;max-h-16&lt;/code&gt;, and many more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--shadow-*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Box shadow utilities like &lt;code&gt;shadow-md&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://tailwindcss.com/docs/theme" rel="noopener noreferrer"&gt;Check the full list here&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Tailwind CSS v4 and Next.js 15 are simplifying frontend development by making configuration less painful and more in line with modern web standards. Using &lt;code&gt;@theme inline&lt;/code&gt;, you can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customize colors, fonts, spacing directly in CSS&lt;/li&gt;
&lt;li&gt;Get full IntelliSense support in your editor&lt;/li&gt;
&lt;li&gt;Avoid bloated config files for simple setups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building your next project with Next.js 15, give this approach a try, you might not even miss your &lt;code&gt;tailwind.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Read more about &lt;a href="http://tailwindcss.com/blog/tailwindcss-v4" rel="noopener noreferrer"&gt;TailwindCSS V4 updates&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Hi, I'm Samit. A Software Developer and a freelancer who’s always on the lookout for exciting, real world projects to build and contribute to. I love hearing from people, whether it’s to collaborate, share ideas, or work together.&lt;/p&gt;

&lt;p&gt;If you're looking to hire a passionate developer or even if you just want to say hi, feel free to check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt; and reach out. I'd love to connect!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>React or Next.js: What to use and When?</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 10 May 2025 09:12:22 +0000</pubDate>
      <link>https://dev.to/samitkapoor/react-or-nextjs-what-to-use-and-when-5hi</link>
      <guid>https://dev.to/samitkapoor/react-or-nextjs-what-to-use-and-when-5hi</guid>
      <description>&lt;p&gt;As a developer who’s been working in React for years, I didn’t expect to fall so hard for Next.js. But once I made the switch, I found myself saying, &lt;strong&gt;“Let’s just Next.js everything.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It started with a side project, I tried next.js and I was hooked. The monorepo-friendly architecture, file based routing, and built-in server-side capabilities really enhanced my developer experience. From that point on, every new project began with &lt;code&gt;npx create-next-app&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;But while Next.js is powerful, it’s not always the right choice. Here are a few real life lessons I’ve learned from switching from React to Next.js:&lt;/p&gt;




&lt;h2&gt;
  
  
  When to choose React?
&lt;/h2&gt;

&lt;h4&gt;
  
  
  1. Client-heavy applications? React might be your best bet.
&lt;/h4&gt;

&lt;p&gt;I’ve found myself struggling in Next.js when building apps that are heavily dependent on client side interactions, like dashboards that don’t care much about SEO and load most of their data via APIs after render. In such cases, the server side magic of Next.js can sometimes get in the way, especially when managing state across dynamic routes or dealing with hydration mismatches.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Backend already deployed? Keep it simple with React.
&lt;/h4&gt;

&lt;p&gt;If you’re only building the frontend and your backend lives elsewhere, React might be the easier and better choice. Next.js shines the most when it handles both frontend and backend logic like when I’m setting up API routes directly in the project. But if I only  need to build frontend I would go with React.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to choose Next.js?
&lt;/h2&gt;

&lt;h4&gt;
  
  
  1. SEO? Go with Next.js.
&lt;/h4&gt;

&lt;p&gt;It’s not that React is bad for SEO, it’s just that Next.js gives you an extra edge. By generating HTML on the server before it hits the browser, Next.js helps web crawlers index your content more effectively.&lt;/p&gt;

&lt;p&gt;I’ve seen improved page rankings and faster content discovery on projects where SEO was critical.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Monorepo-friendly and production-ready out of the box.
&lt;/h4&gt;

&lt;p&gt;One of the things that made me fall in love with Next.js was how easy it is to scale. The file-based routing, API routes, middleware, and even app directory structure make it feel more cohesive and manageable, especially in a monorepo setup.&lt;/p&gt;

&lt;p&gt;React doesn’t impose structure, which can be freeing or frustrating, depending on the size of the project.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 Routing: Manual vs Magic
&lt;/h2&gt;

&lt;p&gt;This was one of the first things that blew my mind.&lt;/p&gt;

&lt;p&gt;In React, I was always setting up &lt;code&gt;react-router-dom&lt;/code&gt;, mapping routes manually, and managing nested routes through config or wrappers. It worked, but it always felt like setup I had to do before actually building anything.&lt;/p&gt;

&lt;p&gt;In Next.js, you just drop a file in your &lt;code&gt;app/&lt;/code&gt; directory and it becomes a route. Done. Need dynamic routes? Just use brackets like &lt;code&gt;[id].tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It feels like the framework &lt;em&gt;wants&lt;/em&gt; you to go fast.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The best part? Clean URLs and layouts come naturally, and you can even create shared layouts without boilerplate. That was a game changer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🚀 Performance: Built-in Wins
&lt;/h2&gt;

&lt;p&gt;Another thing that made me "Next.js everything" was how much performance tuning I &lt;em&gt;didn’t&lt;/em&gt; have to do.&lt;/p&gt;

&lt;p&gt;With React, I’d often reach for tools like &lt;code&gt;React.lazy&lt;/code&gt;, &lt;code&gt;Suspense&lt;/code&gt;, Webpack plugins, manual chunking, or image optimization libraries.&lt;/p&gt;

&lt;p&gt;With Next.js, many of those concerns are handled for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Automatic code splitting.&lt;/li&gt;
&lt;li&gt;🖼️ Built-in image optimization with &lt;code&gt;next/image&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🌍 Static content served via CDN&lt;/li&gt;
&lt;li&gt;✨ Automatic font optimization&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  So, Should You Next.js Everything?
&lt;/h2&gt;

&lt;p&gt;Not necessarily. React is still great and in many cases, it’s exactly what you need.&lt;/p&gt;

&lt;p&gt;But if you’re building a full-stack app, care about performance and SEO, or want a better developer experience out of the box, Next.js makes a compelling case.&lt;/p&gt;

&lt;p&gt;For me, Next.js is my go-to for new projects but there are still times when React.js is the better fit, depending on the project’s needs.&lt;/p&gt;




&lt;p&gt;Hi, I'm Samit. A Software Developer and a freelancer who’s always on the lookout for exciting, real world projects to build and contribute to. I love hearing from people, whether it’s to collaborate, share ideas, or work together.&lt;/p&gt;

&lt;p&gt;If you're looking to hire a passionate developer or even if you just want to say hi, feel free to check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt; and reach out. I'd love to connect!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Understanding onMouseEnter, onMouseOver, and onMouseMove in React</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 03 May 2025 15:56:01 +0000</pubDate>
      <link>https://dev.to/samitkapoor/understanding-onmouseenter-onmouseover-and-onmousemove-in-react-4ce2</link>
      <guid>https://dev.to/samitkapoor/understanding-onmouseenter-onmouseover-and-onmousemove-in-react-4ce2</guid>
      <description>&lt;p&gt;Recently, I was building an animated tabs component for my website, something similar to the animated tab switcher found on Vercel’s dashboard (below)&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%2Fl05g72oxu4rhztc31c8d.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%2Fl05g72oxu4rhztc31c8d.png" alt="animated tab" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was using Framer Motion’s layout animations to animate a background highlight that follows the active tab. Each tab was a &lt;code&gt;div&lt;/code&gt;, and I added &lt;code&gt;onMouseEnter&lt;/code&gt; and &lt;code&gt;onMouseLeave&lt;/code&gt; event listeners to track which tab was currently highlighted. Simple enough, right?&lt;/p&gt;

&lt;p&gt;It worked... until I started moving my mouse quickly between the tabs.&lt;/p&gt;

&lt;p&gt;Sometimes, especially when I moved the mouse at a high speed, none of the tabs appeared to be hovered. The highlight vanished. It was as if my mouse had exited all the elements, even though it was clearly moving over them.&lt;/p&gt;

&lt;p&gt;That behavior didn’t make sense.&lt;/p&gt;

&lt;p&gt;So I dug in. And that’s when I stumbled upon the differences between &lt;code&gt;onMouseEnter&lt;/code&gt;, &lt;code&gt;onMouseOver&lt;/code&gt;, and &lt;code&gt;onMouseMove&lt;/code&gt;. Not only that, I also learned that the way these events behave can vary slightly depending on the HTML element involved.&lt;/p&gt;

&lt;p&gt;I solved the issue by replacing each &lt;code&gt;div&lt;/code&gt; with an &lt;code&gt;li&lt;/code&gt;. This tiny change stabilized the behavior, likely because &lt;code&gt;li&lt;/code&gt; elements come with lighter default styles. But I’ll get to that in a minute.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;onMouseEnter&lt;/code&gt; vs &lt;code&gt;onMouseOver&lt;/code&gt; vs &lt;code&gt;onMouseMove&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;At first glance, these two seem interchangeable. They both fire when your cursor enters an element. But there’s a key difference:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;onMouseEnter&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fires &lt;strong&gt;only once&lt;/strong&gt; when the pointer enters the &lt;em&gt;target element&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does not bubble&lt;/strong&gt;. If a child element is hovered, it won’t trigger again.&lt;/li&gt;
&lt;li&gt;Great for handling &lt;em&gt;overall&lt;/em&gt; entry into a component.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;onMouseOver&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fires &lt;strong&gt;every time&lt;/strong&gt; the pointer enters the &lt;em&gt;target element or any of its children&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does bubble&lt;/strong&gt;, which means it can fire multiple times as the cursor moves over nested elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;onMouseMove&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fires &lt;strong&gt;every time the pointer moves&lt;/strong&gt; within the bounds of an element.&lt;/li&gt;
&lt;li&gt;Can be used for fine-grained tracking e.g., cursor position, hover animations, tooltips.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my case, using any of the above would implement the behaviour I wanted but onMouseEnter was the most efficient since I only wanted to track when cursor enters a tab.&lt;/p&gt;




&lt;h2&gt;
  
  
  So... Why Did Replacing &lt;code&gt;div&lt;/code&gt; with &lt;code&gt;li&lt;/code&gt; Fix It?
&lt;/h2&gt;

&lt;p&gt;This is where it gets interesting.&lt;/p&gt;

&lt;p&gt;While all HTML elements can technically behave the same when styled properly, &lt;strong&gt;semantic HTML elements&lt;/strong&gt; (like &lt;code&gt;li&lt;/code&gt;, &lt;code&gt;button&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;, etc.) often have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fewer browser-default styles (compared to a &lt;code&gt;div&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Simpler box models&lt;/li&gt;
&lt;li&gt;Clearer accessibility and interaction expectations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this specific case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;li&lt;/code&gt; elements are designed to be part of a list, meaning their rendering and hit-box behavior is more consistent in list-like structures.&lt;/li&gt;
&lt;li&gt;The lighter layout overhead of &lt;code&gt;li&lt;/code&gt; might make mouse transitions more predictable, reducing the chance of your cursor skipping out of bounds momentarily at high speed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This difference isn’t always obvious, but it can have a real impact, especially when animations and fast pointer movements are involved.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Choose the Right Event
&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;Recommended Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Trigger once on entering parent&lt;/td&gt;
&lt;td&gt;&lt;code&gt;onMouseEnter&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trigger on entering any child&lt;/td&gt;
&lt;td&gt;&lt;code&gt;onMouseOver&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Track real-time pointer motion&lt;/td&gt;
&lt;td&gt;&lt;code&gt;onMouseMove&lt;/code&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;If your hover-based UI is acting flaky, especially when animations or child elements are involved, don’t immediately blame your logic. The &lt;strong&gt;event type&lt;/strong&gt; and the &lt;strong&gt;element used&lt;/strong&gt; can both significantly affect behavior.&lt;/p&gt;

&lt;p&gt;Sometimes, solving bugs isn’t about changing the code, it’s about choosing the right tags and understanding what’s really going on under the hood.&lt;/p&gt;

&lt;p&gt;If you're working with interactive elements like tabs, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using semantic HTML (&lt;code&gt;li&lt;/code&gt;, &lt;code&gt;button&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Pairing &lt;code&gt;onMouseEnter&lt;/code&gt; with &lt;code&gt;onMouseMove&lt;/code&gt; for better tracking&lt;/li&gt;
&lt;li&gt;Avoiding deep nesting that could confuse bubbling events like &lt;code&gt;onMouseOver&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Hi, I'm Samit. A Software Developer and a freelancer who’s always on the lookout for exciting, real world projects to build and contribute to. I love hearing from people, whether it’s to collaborate, share ideas, or work together.&lt;/p&gt;

&lt;p&gt;If you're looking to hire a passionate developer or even if you just want to say hi, feel free to check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt; and reach out. I'd love to connect!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>mouseevents</category>
    </item>
    <item>
      <title>How to Make Your Website Link Look Amazing on Social Media?</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sat, 26 Apr 2025 10:27:16 +0000</pubDate>
      <link>https://dev.to/samitkapoor/how-to-make-your-website-link-look-amazing-on-social-media-58n1</link>
      <guid>https://dev.to/samitkapoor/how-to-make-your-website-link-look-amazing-on-social-media-58n1</guid>
      <description>&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%2Flm8809rvz89c9hnjj82j.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%2Flm8809rvz89c9hnjj82j.png" alt="Twitter example of link" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you share the link to your project on social media platforms like Twitter, Peerlist, LinkedIn, and others, having a preview banner(like the one shown above) can significantly increase the chances of users clicking on it. A good looking preview not only grabs attention but also improves the visibility of your link, driving more traffic to your project.&lt;/p&gt;

&lt;p&gt;In this article, I'll explain how social media link previews work and how you can easily make your website links look amazing when shared online.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does It Work?
&lt;/h2&gt;

&lt;p&gt;When you paste a link on social media, the platform doesn’t just display the raw URL. Instead, it tries to fetch extra information from the website to create a more engaging preview. &lt;/p&gt;

&lt;p&gt;But how does it know what title, description, or image to show?&lt;br&gt;&lt;br&gt;
That's where &lt;strong&gt;Open Graph meta tags&lt;/strong&gt; (originally introduced by Facebook) and &lt;strong&gt;Twitter Card meta tags&lt;/strong&gt; come into play.&lt;/p&gt;

&lt;p&gt;These are special HTML tags that you add inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of your webpage. They tell social media platforms exactly what content to display when someone shares your link, including the page title, description, and a thumbnail image.&lt;/p&gt;

&lt;p&gt;Without these tags, platforms will either guess the information or just show a plain link without any visuals.&lt;br&gt;&lt;br&gt;
By setting up the right meta tags yourself, you take full control over how your website appears, making it look clean, professional, and much more clickable.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic Tags You Need
&lt;/h2&gt;

&lt;p&gt;To set up a beautiful link preview, you mainly need to add a few meta tags inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of your HTML page. Here are the important ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="c"&gt;&amp;lt;!-- Open Graph Meta Tags --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Your Website Title Here"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"A short description about your website or page."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://yourwebsite.com/your-preview-image.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://yourwebsite.com/"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Twitter Card Meta Tags --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:card"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"summary_large_image"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Your Website Title Here"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"A short description about your website or page."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://yourwebsite.com/your-preview-image.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;You can also include more information about your website!&lt;br&gt;
Read here to know more: &lt;a href="https://developer.x.com/en/docs/x-for-websites/cards/guides/getting-started" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://ogp.me/" rel="noopener noreferrer"&gt;OpenGraph&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Long Does It Take for Changes to Reflect?
&lt;/h2&gt;

&lt;p&gt;After you update or add Open Graph and Twitter Card meta tags, it’s important to know that changes might not show up instantly everywhere.&lt;/p&gt;

&lt;p&gt;Most social media platforms cache the preview information the first time they see a link. This means if you shared your link before setting the correct meta tags, platforms like X, LinkedIn, or Facebook might continue showing the old preview for some time.&lt;/p&gt;

&lt;p&gt;In general, once you force a re-crawl using their official tools, changes should reflect within a few minutes to an hour.&lt;/p&gt;

&lt;p&gt;Here are some tools to see how your website will look in preview: &lt;a href="https://developers.facebook.com/tools/debug/" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;, &lt;a href="https://www.linkedin.com/post-inspector/inspect/readmechef.com" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Adding proper preview banners to your website is a small but powerful improvement that can make a big difference in how your project is perceived online.&lt;br&gt;&lt;br&gt;
It helps your link stand out, grabs more attention, and can drive more traffic to your site.&lt;/p&gt;

&lt;p&gt;Now that you know how it works, take a few minutes to set it up for your own website.  &lt;/p&gt;

&lt;p&gt;If you found this article helpful, feel free to share it with someone who might need it too. 🚀&lt;/p&gt;




&lt;p&gt;Hi, I'm Samit. A Software Developer and a freelancer who’s always on the lookout for exciting, real world projects to build and contribute to. I love hearing from people, whether it’s to collaborate, share ideas, or work together.&lt;/p&gt;

&lt;p&gt;If you're looking to hire a passionate developer or even if you just want to say hi, feel free to check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt; and reach out. I'd love to connect!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I won Peerlist x Aceternity UI animation challenge: My problem solving approach</title>
      <dc:creator>Samit Kapoor</dc:creator>
      <pubDate>Sun, 20 Apr 2025 17:50:08 +0000</pubDate>
      <link>https://dev.to/samitkapoor/how-i-won-peerlist-x-aceternity-ui-animation-challenge-my-problem-solving-approach-84d</link>
      <guid>https://dev.to/samitkapoor/how-i-won-peerlist-x-aceternity-ui-animation-challenge-my-problem-solving-approach-84d</guid>
      <description>&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%2F84jz0waufeyfwdiztctm.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%2F84jz0waufeyfwdiztctm.png" alt="My submissions" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://courageous-bunny-d56f10.netlify.app" rel="noopener noreferrer"&gt;Click here to see my submissions&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/samitkapoor/peerlist-ui-challenge" rel="noopener noreferrer"&gt;Click here for the repository&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 What is the UI Animation Challenge?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://peerlist.io/challenges/ui-animation-challenge" rel="noopener noreferrer"&gt;UI Animation Challenge&lt;/a&gt; was a 5-day design-to-code event hosted by &lt;a href="https://peerlist.io" rel="noopener noreferrer"&gt;Peerlist&lt;/a&gt; in collaboration with &lt;a href="https://ui.aceternity.com" rel="noopener noreferrer"&gt;Aceternity UI&lt;/a&gt;. Each day, participants were given an animated UI component and were challenged to bring it to life.&lt;/p&gt;

&lt;p&gt;There were six winners in total:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One prize winner received access to the highly acclaimed UI Animation course by &lt;a href="https://x.com/emilkowalski_" rel="noopener noreferrer"&gt;Emil Kowalski&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Five additional winners received a lifetime subscription to Aceternity UI Pro&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I participated in the challenge and won a lifetime subscription to Aceternity UI Pro. In this article, I’ll walk you through my problem solving approach for each of the five daily challenges, how I interpreted the prompts, made design decisions, and tackled technical hurdles along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 1 – Fluid Menu Animation
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://peerlist.io/challenges/ui-animation-challenge" rel="noopener noreferrer"&gt;View the challenge&lt;/a&gt;&lt;br&gt;
🎯 &lt;a href="https://peerlist.io/scroll/post/ACTHMQL9QPGJ8PJDBHDNLD6RAB99EO" rel="noopener noreferrer"&gt;View my submission&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💭 Initial Thoughts
&lt;/h3&gt;

&lt;p&gt;The moment I saw the reference video, it was clear that it was gooey animation. I'd heard of them before, but never actually tried building one myself. Honestly, I had no idea how it worked under the hood or how the icons were blending into each other like that.&lt;/p&gt;

&lt;p&gt;Still, it felt doable if broken down into smaller steps. The animation made sense to me, all the icons seemed to be hidden behind the main menu button and then popped out vertically when the menu was opened. So the plan was to stack them all in the same spot using absolute positioning, and then animate them along the Y axis when triggered.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Building It
&lt;/h3&gt;

&lt;p&gt;I started off by designing each icon button, just simple circles with a background color and full border radius. A toggle state was added to track whether the menu was open or closed, and from there, the layout for the open state was built. I used &lt;code&gt;motion&lt;/code&gt; and &lt;code&gt;AnimatePresence&lt;/code&gt; from &lt;code&gt;framer-motion&lt;/code&gt; to animate the transition between state&lt;/p&gt;

&lt;p&gt;That part was pretty straightforward and felt familiar.&lt;/p&gt;

&lt;p&gt;The tricky bit was the actual &lt;em&gt;gooey&lt;/em&gt; effect. Since I hadn’t done it before, I went straight to the internet to get an idea of how it works. Turned out, it could be done using SVG filters like &lt;code&gt;feGaussianBlur&lt;/code&gt; and &lt;code&gt;feColorMatrix&lt;/code&gt;, which let elements blend and stretch into each other.&lt;/p&gt;

&lt;p&gt;After applying the filter and messing around with the values a bit, the gooey look started to come together. It was super satisfying to see it work, especially considering I started off not knowing how to even approach it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 2 – Dynamic Status Indicator
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://peerlist.io/challenges/ui-animation-challenge" rel="noopener noreferrer"&gt;View the challenge&lt;/a&gt;&lt;br&gt;
🎯 &lt;a href="https://peerlist.io/scroll/post/ACTHJKR6JQQDOQNDL1RKAAKPL7A88K" rel="noopener noreferrer"&gt;View my submission&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💭 Initial Thoughts
&lt;/h3&gt;

&lt;p&gt;Out of all the challenges, this one felt like the easiest. It was pretty straightforward, and I’d already worked on similar entry and exit animations using &lt;code&gt;framer-motion&lt;/code&gt; in the past. I could tell what was happening behind the scenes just by watching the reference video a couple of times.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Building It
&lt;/h3&gt;

&lt;p&gt;The component had three states: &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;success&lt;/code&gt;, and &lt;code&gt;error&lt;/code&gt;. I started by building the UI for each state separately. Then, I set up a &lt;code&gt;setInterval&lt;/code&gt; to automatically switch between the status.&lt;/p&gt;

&lt;p&gt;To animate the transitions between the different states, I used &lt;code&gt;AnimatePresence&lt;/code&gt; from &lt;code&gt;framer-motion&lt;/code&gt;. But early on, I ran into a weird issue the component would slightly distort during transitions. That’s when I discovered that &lt;code&gt;AnimatePresence&lt;/code&gt; supports different modes, and switching to &lt;code&gt;wait&lt;/code&gt; mode fixed the glitch. In this mode, the next element waits for the current one to fully exit before entering, which ended up making the transition much smoother.&lt;/p&gt;

&lt;p&gt;Once everything was working, I was pretty happy with the result and submitted it.&lt;/p&gt;

&lt;p&gt;I looked at it again later and realized I had missed two important details:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The direction of the text animation is actually different depending on the state.

&lt;ul&gt;
&lt;li&gt;“Analyzing Transaction” (loading) enters from the left, suggesting progress or motion.
&lt;/li&gt;
&lt;li&gt;“Transaction Safe” (success) comes in from the right, giving it a sense of completion or arrival.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The width of the container animated during state changes, which I completely overlooked.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Looking back, I think I was a bit too confident while building this one. Since I already felt comfortable with the concept, I might’ve rushed through it and didn’t pay close enough attention to the finer details. It’s wild how much nuance there can be in animations that seem super simple at first glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 3 – Animated Checkbox
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://peerlist.io/challenges/ui-animation-challenge" rel="noopener noreferrer"&gt;View the challenge&lt;/a&gt;&lt;br&gt;
🎯 &lt;a href="https://peerlist.io/scroll/post/ACTHR86GKRRL9K6AN1MP7MDJNAL8BE" rel="noopener noreferrer"&gt;View my submission&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💭 Initial Thoughts
&lt;/h3&gt;

&lt;p&gt;This one was a bit tricky. I could tell right away that the checkbox border animation was some sort of path animation, most likely done using SVG, but I had no real experience implementing one before. I did understand how to handle the text animation when an item is marked complete, so I figured I’d start there and build things up gradually - same mindset as Day 1. Just take it step by step, learn what’s needed along the way, and eventually the full component would come together.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Building It
&lt;/h3&gt;

&lt;p&gt;I kicked things off by setting up a basic todo list UI, similar to the prompt. Got a list of checkboxes, and added a simple animated strikethrough for the text when a task was marked as done.&lt;/p&gt;

&lt;p&gt;Then came the tricky part: the border animation on the checkbox itself. I headed on to the internet and came across &lt;a href="https://www.cassie.codes/posts/creating-my-logo-animation" rel="noopener noreferrer"&gt;this article&lt;/a&gt; by Cassie Evans, which explained how &lt;code&gt;stroke-dasharray&lt;/code&gt; and &lt;code&gt;stroke-dashoffset&lt;/code&gt; work together to create path animations.&lt;/p&gt;

&lt;p&gt;Using that, I created an SVG &lt;code&gt;rect&lt;/code&gt; and animated its stroke to draw around the checkbox using &lt;code&gt;framer-motion&lt;/code&gt;. Once I figured out how the stroke lengths corresponded to the path, it all clicked into place.&lt;/p&gt;

&lt;p&gt;But looking back, I missed 1 detail here too:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The checkbox text actually shakes horizontally when clicked. I completely missed it in the excitement of figuring out path animations.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By this point, I knew I had to step up for the last two challenges. I had already missed three small details across the first three days. If I wanted to stand out and win something, I needed to slow down a bit and focus harder going forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 4 – Animated Toggles
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://peerlist.io/challenges/ui-animation-challenge" rel="noopener noreferrer"&gt;View the challenge&lt;/a&gt;&lt;br&gt;
🎯 &lt;a href="https://peerlist.io/scroll/post/ACTHQ79E89LNA9AQPC68PO7PDEQNLQ" rel="noopener noreferrer"&gt;View my submission&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💭 Initial Thoughts
&lt;/h3&gt;

&lt;p&gt;This one needed the most focus so far. I really had to study the animation closely to figure out what was going on. Also, great timing , I happened to be on a road trip with my family that day, building this from the back seat of a moving car.&lt;/p&gt;

&lt;p&gt;After watching the reference video a few times, I realized there was a background div behind the toggles that slides depending on which button is clicked. What made it tricky was how smooth the whole transition felt. When you click “Premium,” the heading seems to slide down while the “Monthly · Annual” options come up, it gives the illusion of the whole component zooming in. I also noticed there was likely a fade involved to help sell the motion.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Building It
&lt;/h3&gt;

&lt;p&gt;I started small again, just built a basic toggle UI with no animations or active states. Then I added the sliding background div to indicate the selected option. Once that was working, I created a separate component for the active “Premium” state and wired it up with &lt;code&gt;AnimatePresence&lt;/code&gt; to handle entry and exit transitions.&lt;/p&gt;

&lt;p&gt;I spent quite a bit of time here tweaking values to make sure the motion felt seamless and unified, like it was all part of one animation instead of separate moving parts. I also made a conscious effort not to rush this one, especially after missing some details in the earlier challenges.&lt;/p&gt;

&lt;p&gt;I ended up submitting it later in the day after getting home from the trip and giving it a proper final review. Personally, I think this was my strongest submission of the week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 5 – Shared Layout Tabs
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://peerlist.io/challenges/ui-animation-challenge" rel="noopener noreferrer"&gt;View the challenge&lt;/a&gt;&lt;br&gt;
🎯 &lt;a href="https://peerlist.io/scroll/post/ACTH7BJLO7LBGDLLOF9B78GO9GPKJ8" rel="noopener noreferrer"&gt;View my submission&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💭 Initial Thoughts
&lt;/h3&gt;

&lt;p&gt;This was hands down the toughest challenge of the week. I had done something a bit similar before using Hero animations in Flutter, so I had a rough idea of what was going on, but I didn’t really know how to approach it in the React + Framer Motion.&lt;/p&gt;

&lt;p&gt;The individual views were simple to build. It was the smooth transition between them that had me scratching my head. Once again, I was back in familiar territory: unsure how to do it, but confident I could figure it out step by step.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Building It
&lt;/h3&gt;

&lt;p&gt;I started by laying out the basic structure, added the heading, animated tab bar, and built out each view without worrying about transitions at first. I wanted to make sure everything looked good statically before diving into animations.&lt;/p&gt;

&lt;p&gt;Once I was happy with the layout, I went down learning how to animate between views. That’s when I discovered &lt;code&gt;framer-motion&lt;/code&gt;’s layout animations, and I found &lt;a href="https://blog.maximeheckel.com/posts/framer-motion-layout-animations" rel="noopener noreferrer"&gt;this article&lt;/a&gt; which explained the concept really well.&lt;/p&gt;

&lt;p&gt;After reading through it and experimenting a bit, things started to click. I took my time with this one, no rushing, and paid extra attention to the little details I had missed earlier in the week. Finally, I submitted the component and wrapped up the challenge.&lt;/p&gt;

&lt;p&gt;Felt like the perfect way to end the week, learning something completely new and actually getting it to work!&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Back
&lt;/h2&gt;

&lt;p&gt;This challenge was honestly one of the most fun and rewarding things I’ve done in a while. I had an absolute blast learning new concepts, pushing myself out of my comfort zone, and figuring things out as I went. I don’t think I’ve ever felt this challenged creatively and technically and that’s exactly what made it so exciting.&lt;/p&gt;

&lt;p&gt;It’s a solid reminder that consistent challenges like this are a great way to level up. I’m definitely going to make it a habit to take on more of these, just to keep learning, building, and improving as a developer.&lt;/p&gt;

&lt;p&gt;Can’t wait to participate in more challenges like this in the future!&lt;/p&gt;




&lt;p&gt;Hi, I'm Samit. A Software Developer and a freelancer who’s always on the lookout for exciting, real world projects to build and contribute to. I love hearing from people, whether it’s to collaborate, share ideas, or work together.&lt;/p&gt;

&lt;p&gt;If you're looking to hire a passionate developer or even if you just want to say hi, feel free to check out my &lt;a href="https://samitkapoor.com" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt; and reach out. I'd love to connect!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>peerlist</category>
      <category>aceternity</category>
    </item>
  </channel>
</rss>
