<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ coding - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ coding - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 21 May 2026 04:58:04 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/coding/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Ask a Great (Technical) Question: The Art of Getting Help Debugging Code ]]>
                </title>
                <description>
                    <![CDATA[ Computers will, 100% of the time, without fail, do exactly what you tell them to do. It's getting them to do what you want them to do that's the real trick. The gap between what you tell the computer  ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-ask-a-great-technical-question/</link>
                <guid isPermaLink="false">69b997b8c22d3eeb8ae5a273</guid>
                
                    <category>
                        <![CDATA[ questions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ discord ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Pete Lamonica ]]>
                </dc:creator>
                <pubDate>Tue, 17 Mar 2026 18:04:40 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/00747953-54ab-4027-8eaa-6f85a4e74b51.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Computers will, 100% of the time, without fail, do exactly what you <em>tell</em> them to do. It's getting them to do what you <em>want</em> them to do that's the real trick.</p>
<p>The gap between what you <em>tell</em> the computer to do and what you <em>want</em> the computer to do is where bugs are born and thrive.</p>
<p>As a moderator on the <a href="https://discord.gg/KVUmVXA">freeCodeCamp Discord</a>, I frequently see people pop in to say, “I did everything exactly right but my code isn’t working!” These people know what they <em>want</em> their code to do. But they didn’t <em>tell</em> the computer how to do it properly.</p>
<p>To resolve their bug, they must align their desires — their mental model of their code’s behavior — with their code. <strong>Assumptions are the truses that preserve that gap.</strong></p>
<h2 id="heading-the-problem-with-assumptions">The Problem with Assumptions</h2>
<p>Let’s say that I'm working on a webpage and I want to set an element’s background to be blue. It’s not working as I desire. It’s setting the text color instead of the background color.</p>
<p>I engage my coworker for help. I say to her, “I told the computer to make the background blue. But it’s setting the text color instead!”</p>
<p>My problem is that I <em>didn’t</em> tell the computer to change the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/background-color">background color</a>. I instead mistakenly used the <code>color</code> <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color">property</a>. There’s no way that my coworker could know that I was using the wrong property. So my assumption prevented her from helping me.</p>
<h2 id="heading-the-components-of-a-great-question">The Components of a Great Question</h2>
<p>Getting help takes effort. The more work you put into seeking help, the more likely you’ll be to obtain the help you need. In my experience, there are 3 components to a great question when you need technical assistance. <strong>Great questions contain <em>all</em> of these components</strong>.</p>
<ol>
<li><p>The code that contains the problem</p>
</li>
<li><p>Any error messages you’re seeing</p>
</li>
<li><p>A description of the issue containing <em>all</em> of the following:</p>
<ul>
<li><p>The exact steps to reproduce the issue</p>
</li>
<li><p>The expected result</p>
</li>
<li><p>The actual result</p>
</li>
</ul>
</li>
</ol>
<p>Below, I’ll break down each component in detail in case you’re not sure how to provide it when asking for help.</p>
<h3 id="heading-the-code-that-contains-the-problem">The Code that Contains the Problem</h3>
<p>This is harder than it sounds. Frequently, the reason I fail to fix a bug by myself is that I’m looking in the wrong place. I may be looking in the wrong function, file, or even project! If I go to my coworker for help and only provide her the code that I <em>think</em> contains the problem, then she may not be able to help me out.</p>
<p>This means that it’s important to provide as much context as possible. This increases the chances that the code you share with the people helping you will contain the information they need to help you solve your problem.</p>
<p>Even with decades of experience coding, I frequently have doubts about how certain code will behave. Being able to run the code and experiment with it (add logs, attach a debugger, try different inputs, and so on) is a big part of my process.</p>
<p>There’s lots of ways you might transmit your code to someone to get some help. Here’s some examples:</p>
<h4 id="heading-for-large-projects">For Large Projects</h4>
<p>If you’re having trouble with a large project (something more than one file or more than a couple hundred lines of code). Then your best bet is to share a <a href="https://github.com">GitHub</a> repo containing all the code.</p>
<p>Alternatively, you might create a “minimal reproduction.” If you can make the problem happen in the context of a small amount of code, then you can share that code instead. This can dramatically reduce the amount of work others need to do to help you and increase your chances of getting the answers you’re seeking.</p>
<p>Note: When working on a project for a client or employer, you might not be able to get help from outside sources due to your inability to share the relevant code. Don't share your employer’s or clients’ code publicly unless you have explicit permission to do so!</p>
<h4 id="heading-for-single-file-projects">For Single File Projects</h4>
<p>If your project is just one or two files or you’re creating a minimal reproduction of the issue, then you might be able to in-line your code in a chat message or create a <a href="https://gist.github.com">GitHub Gist</a> containing the relevant code.</p>
<p>Alternatively, you could use a tool like <a href="https://codepen.io">CodePen</a> or <a href="https://stackblitz.com">StackBlitz</a> to quickly generate a reproduction of the problem you’re facing.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736374915253/1aad0c65-c5dc-41df-9eff-d8cb7c0f9a84.png" alt="A not-yet-sent Discord message containing a code block. It starts with three backticks and the letters &quot;js&quot; on their own line, then contains some JavaScript code followed by three more backticks on their own line at the end." style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<h4 id="heading-for-freecodecamp-lessons">For freeCodeCamp Lessons</h4>
<p>Many of the questions I get on the freeCodeCamp Discord are regarding lessons in the learning platform (the curriculum). When asking a question about one of these lessons, make sure you include:</p>
<ol>
<li><p>All the code from the editor panel (that is, all the code you have written or modified)</p>
</li>
<li><p>A link to the step</p>
</li>
</ol>
<p>Without these two things, providing help gets dramatically harder.</p>
<h3 id="heading-error-messages">Error Messages</h3>
<p>When you’re a newer developer, error messages can be <em>very intimidating.</em> It’s understandable that you might skim over them as they don’t make sense and you’re not sure how to leverage them to solve your problem.</p>
<p><strong>Reading your error messages carefully</strong> can be one of the first steps you take to becoming a stronger developer. But even if you don’t know what to make of the message, when seeking help, make sure you give others with experience in reading those messages the opportunity to do so. If there are any error messages in your <a href="https://developer.chrome.com/docs/devtools/console">console</a> or terminal, copy/paste them <em>in their entirety</em> to your post asking for help.</p>
<h3 id="heading-description-of-the-issue">Description of the Issue</h3>
<p>When asking for help, you should <strong>consider that the person or people you’re asking might not have any context on your situation</strong>. It’s up to you to give them the context they need. To make sure you have given that context, include each of the following:</p>
<h4 id="heading-steps-to-reproduce-the-issue">Steps to Reproduce the Issue</h4>
<p>What, specifically, did you do that led you to encounter the problem you have? Be as detailed as possible here. Include things like, “I clicked the ‘Submit’ button,” or “I opened <code>https://www.example.com</code> in my browser.”</p>
<h4 id="heading-the-expected-result">The Expected Result</h4>
<blockquote>
<p>Me: “My text is blue!”<br>My coworker: “That’s nice.”</p>
</blockquote>
<p>My coworker wasn’t being dismissive of my problem. She just didn’t know whether it <em>was</em> a problem or not. Maybe I <em>wanted</em> the text to be blue. Maybe the blue text had nothing to do with my problem. Maybe the text only turns blue under certain circumstances.</p>
<p>If I had told my coworker that I expected the background to be blue rather than the text, she might have quickly realized what I did wrong and offered up a good suggestion on how to fix it.</p>
<h4 id="heading-the-actual-result">The Actual result</h4>
<blockquote>
<p>Me: “I wanted my background to be blue!”<br>My coworker: “That’s nice.”</p>
</blockquote>
<p>Forgetting to give the actual result is pretty much just as useless as forgetting to give the expected result. The expected and actual result of your code are <em>both</em> critical to a well-composed question.</p>
<p>When it comes to sharing actual results, screenshots or videos can be quite handy. Just make sure you’re not relying on them to the exclusion of the other components of a good question.</p>
<h2 id="heading-example-question">Example Question</h2>
<p>Here’s an example of what putting all this guidance together might yield:</p>
<blockquote>
<p>I'm on this step: <a href="https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures-v8/learn-introductory-javascript-by-building-a-pyramid-generator/step-33">https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures-v8/learn-introductory-javascript-by-building-a-pyramid-generator/step-33</a></p>
<p>I tried putting in this code:</p>
<pre><code class="language-javascript">for (iterator; condition; iteration) {

}
</code></pre>
<p>I expected it to pass, but instead, it gave me an error reading:</p>
<pre><code class="language-plaintext">ReferenceError: iterator is not defined
</code></pre>
<p>Can anyone help me figure out what I'm doing wrong? Here’s a screenshot of the step and error:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736374001287/ed083d56-ae60-40f8-a985-e9ce21a919ad.png" alt="A step on the freeCodeCamp website showing instructions and errors." style="display:block;margin:0 auto" width="600" height="400" loading="lazy"></blockquote>
<p>The question isn’t long, but it contains all the elements of a quality question as described by this article. It gives the code that contains the problem (including a link to the freeCodeCamp step), the error message that is shown, and the expectations (that it should pass) and actual result (that an error message is shown). It even includes a helpful screenshot showing how the error and result are presented.</p>
<h2 id="heading-closing-thoughts">Closing Thoughts</h2>
<p>This feels like a whole lot of effort. I just want my problem solved. Do I <strong>really</strong> need to do all of this???</p>
<p>Short answer? Yes. But only because <strong>it’s <em>less</em> effort than engaging in a prolonged back and forth as the people trying to help you attempt to get this information.</strong> Not just that, but if you go through these steps and collect this information, you might even find that you solve your problem yourself without needing to engage others.</p>
<p>This process might feel tedious at first, but like many things in life, if you practice it regularly then it becomes easier.</p>
<p>You’ve got this. 😎</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Storyteller: A Medium For Guiding Others Through Code ]]>
                </title>
                <description>
                    <![CDATA[ As a computer science instructor, I have long wished that there was a better way to guide others through my code. When I was first learning to program, I was a big fan of traditional programming books ]]>
                </description>
                <link>https://www.freecodecamp.org/news/storyteller-a-medium-for-guiding-others-through-code/</link>
                <guid isPermaLink="false">69a23fd4d4053a09f35c3d3e</guid>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code playbacks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mark Mahoney ]]>
                </dc:creator>
                <pubDate>Sat, 28 Feb 2026 01:07:32 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5fc16e412cae9c5b190b6cdd/902c2299-ea98-4136-8ee8-36668f0c08ee.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a computer science instructor, I have long wished that there was a better way to guide others through my code. When I was first learning to program, I was a big fan of traditional programming books. I have shelves and shelves of 800+ page books covering different programming languages and technologies.</p>
<p>I have known for a while now that most learners today don't share my love of big thick books, and to be honest, I rarely read those books in their entirety. Those big books often had a lot more exposition about the code than was probably needed. As a book buyer I wanted to make sure that I was getting my money's worth so the thicker they were, the better. It is much more common these days for learners to consume blog based tutorials and videos.</p>
<p>If you're learning to code right now, you've probably experienced the frustration of these formats too. I want to share something I've been working on that might help.</p>
<h2 id="heading-blogs-and-videos"><strong>Blogs and Videos</strong></h2>
<p>Blog-style tutorials mix code and the explanation of it in a top-to-bottom fashion. Scrolling through these web-based explanations feels familiar and one can copy and paste with ease. However, linking the explanation of the code and the code itself has always been less than ideal. Often I find myself jumping around the blog post wishing I could see the entire code example while working through the explanation. Instead, I am only able to see small parts of the code and it is challenging to see how those parts relate to other parts.</p>
<p>Video tutorials are very popular these days. They solve some of the problems associated with blog-style tutorials. Videos are great because you get two streams of information: the author's audible narrative and the code being written. A viewer can focus on the two streams simultaneously. However, videos have some problems too.</p>
<h3 id="heading-viewing-videos"><strong>Viewing Videos</strong></h3>
<p>From the perspective of the viewer, videos are hard to search through and are not useful as a copy and paste source or a code reference. More importantly, though, they discourage the viewer from taking their time and reflecting on the material. Often, when I am viewing a video tutorial I don't pause and let concepts sink in before the video moves on. Yes, I could be more disciplined and pause and rewind more often but usually I don't.</p>
<h3 id="heading-making-videos"><strong>Making videos</strong></h3>
<p>From the perspective of the video creator, it is clear that not all code being developed is interesting to watch. Some of it is not really worth showing the viewer. Not all video creators can keep the narrative interesting the whole time.</p>
<p>I know I struggle with the 'performance' aspect of making videos (you won't find me coding on Twitch anytime soon). Many times after I am done making a video, as I review it, I wish I had mentioned something that I forgot. It is hard to go back and edit the video without scrapping it and starting over.</p>
<h2 id="heading-storyteller"><strong>Storyteller</strong></h2>
<p>I have created a new medium to guide viewers through code examples. It combines the best of books, blog posts, and videos. This new medium allows a developer to write code using a top-notch editor (Visual Studio Code) and then replay the development of that code in the browser.</p>
<p>The author can add comments at important points in the evolution of the code. The comments can include text, hand drawn pictures, screenshots, and audio and video recordings. This allows the author to add visualizations that we have in our heads but don't make it into the code itself. The tool is called <a href="https://github.com/markm208/storyteller">Storyteller</a>.</p>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/67df75cfc82238bba0f330b3/82dcb5c8-999f-432f-bd60-adcb3d8b9889.png" alt="82dcb5c8-999f-432f-bd60-adcb3d8b9889" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>Here are a few examples of a 'playback':</p>
<ul>
<li><p><a href="https://playbackpress.com/books/pybook/chapter/2/10">Enlarging a Picture (Python)</a></p>
</li>
<li><p><a href="https://playbackpress.com/books/cppbook/chapter/8/8">Dynamic Variables and Pointers (C++)</a></p>
</li>
</ul>
<p>These work best on a big screen. If you are viewing a playback on a small screen you can view it in 'blog' mode (there is button in the top right to switch from 'code' mode to 'blog' mode).</p>
<p>I have created groups of these guided code walk-throughs to help me teach different topics to my students. These are all free and hosted on a website I created called <a href="https://playbackpress.com/books">Playback Press</a>. Here are some of the 'books' I have created so far:</p>
<ul>
<li><p><a href="https://playbackpress.com/books/cppbook/">An Animated Introduction to Programming in C++</a></p>
</li>
<li><p><a href="https://playbackpress.com/books/pybook/">An Animated Introduction to Programming with Python</a></p>
</li>
<li><p><a href="https://playbackpress.com/books/webdevbook/">An Introduction to Web Development from Back to Front</a></p>
</li>
<li><p><a href="https://playbackpress.com/books/cljbook/">An Animated Introduction to Clojure</a></p>
</li>
<li><p><a href="https://playbackpress.com/books/exbook/">An Animated Introduction to Elixir</a></p>
</li>
<li><p><a href="https://playbackpress.com/books/sqlbook/">Database Design and SQL for Beginners</a></p>
</li>
<li><p><a href="https://playbackpress.com/books/flutterbook/">Mobile App Development with Dart and Flutter</a></p>
</li>
<li><p><a href="https://playbackpress.com/books/patternsbook/">OO Design Patterns with Java</a></p>
</li>
</ul>
<p>I usually assign these as readings in my classes instead of using expensive textbooks. It is a lot easier for me to write several programs than it is to find a perfect textbook.</p>
<p>I also use them for in-class demos instead of writing code live. This makes code demos flow much faster and smoother. If I make an interesting mistake while preparing the code I can still highlight it with a comment. If I make an uninteresting or embarrassing mistake I can just ignore it and the students won't focus on it.</p>
<h3 id="heading-the-advantages-of-code-playbacks"><strong>The Advantages of Code Playbacks:</strong></h3>
<ul>
<li><p>The primary focus is on the code. It is always visible and easy to search and navigate.</p>
</li>
<li><p>Since the code is so accessible, the explanation of it tends to be short and concise.</p>
</li>
<li><p>The narrative can include whiteboard style drawings, screenshots, or videos of running code in addition to a text explanation.</p>
</li>
<li><p>As an author, I can review the code several times and add/edit comments each time I go through it. I don't have to give a perfect performance like I do with a video.</p>
</li>
<li><p>Comment points highlight when the author wants the viewer to take a moment to really think about the code and reflect on it. The playback only moves forward when the viewer is ready.</p>
</li>
<li><p>The code mentioned in a comment can be highlighted so the viewer knows exactly where they should be looking.</p>
</li>
<li><p>The code can be downloaded at any point in the playback. Then a viewer can run it, change it, and add to it.</p>
</li>
<li><p>The tool is a language independent editor plug-in and can be used to describe programs in any language.</p>
</li>
<li><p>Viewers only need a web browser to go through a playback.</p>
</li>
</ul>
<p>Recently, I've been exploring how to make playbacks even more useful for learners.</p>
<h2 id="heading-ai-as-an-infinitely-patient-tutor"><strong>AI as an Infinitely Patient Tutor</strong></h2>
<p>I have extended code playbacks to include an AI tutor. One thing I've learned in my years of teaching is that students often hesitate to ask questions. They worry about looking foolish, or they don't want to slow down the class, or they simply can't articulate what's confusing them.</p>
<p>What if every student had access to a patient tutor who never got frustrated with repeated questions and could explain concepts in multiple ways until something clicked?</p>
<p>I've integrated AI directly into the playback experience. As students work through a playback, they can ask questions about anything they're seeing. This might be a specific line of code, a concept I mentioned in a comment, or how something connects to material from earlier in the playback. The AI has full context. It can see the code, it understands where the student is in the playback, and it can provide explanations tailored to that exact moment. The AI is right there <em>with</em> the student, looking at the same code, understanding the same context.</p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/WAPql5KZFR4?si=jFnCqidSTtfaZA4e" frameborder="0" allowfullscreen="" title="Embedded content" loading="lazy"></iframe></div>

<p>The AI can also generate self-grading multiple choice questions based on the code and comments in a playback. These low-stakes quizzes make the learning experience more engaging and help learners check their understanding as they go.</p>
<p>Let me be clear: the AI doesn't replace me as an instructor. I still create the playbacks. I still decide what concepts to cover, what order to present them, and what examples best illustrate the ideas. The AI is an extension of my teaching, not a replacement for it.</p>
<p>Note: The AI features are available to registered users on <a href="https://playbackpress.com/books">Playback Press</a>. Registration is free but logging in is required to access the AI tutor. If you want to see what this feels like, try one of the playbacks linked above and ask the AI a question about what you're seeing.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>My goal has always been to help people learn to code. Books gave us depth but demanded commitment. Blogs gave us accessibility but fragmented the code. Videos gave us narrative but took away control. Playbacks keep the code front and center while letting learners move at their own pace and reflect when they need to. Adding AI doesn't change that philosophy, it just means there's always someone available to answer questions. Together, they get closer to the experience of having an expert sit beside you and walk you through a program. That's what I've been trying to build, and I think we're getting there.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Go From Hello World to Building Real-World Applications ]]>
                </title>
                <description>
                    <![CDATA[ Many developers start learning programming by building simple projects like todo apps, calculators, and basic CRUD applications. These projects are useful at the beginning, as they help you understand how a programming language works and give you the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-go-from-hello-world-to-building-real-world-applications/</link>
                <guid isPermaLink="false">697d098607632dbd100433e8</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Learning Journey ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Spruce Emmanuel ]]>
                </dc:creator>
                <pubDate>Fri, 30 Jan 2026 19:41:58 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769802056548/2b1b2ede-5f7f-423f-b6ee-19e0c0ac7b43.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Many developers start learning programming by building simple projects like todo apps, calculators, and basic CRUD applications. These projects are useful at the beginning, as they help you understand how a programming language works and give you the confidence to start building things. But for many developers, progress stops there.</p>
<p>Real world applications aren’t just about showing data on a screen. They solve real problems, work with real users, and handle situations that don’t always go as planned. This is where many developers struggle.</p>
<p>When I review junior developers’ résumés, I notice a common pattern: the projects section is often filled with beginner apps that look very similar. In today’s job market, this is usually not enough. Employers want to see that you can build something useful, something people would actually use.</p>
<p>The goal of this article is to help you move past simple Hello World projects like todo apps, calculators, and basic CRUD applications. By the end, you’ll understand how to approach building real applications that solve real problems and feel closer to what is built in the real world.</p>
<p>You might be wondering why you should listen to me.</p>
<p>Over the last 10 years, I’ve spent a lot of time building, breaking, and rebuilding software. I have experimented, failed many times, and eventually built applications that thousands of people use every day. A few weeks ago, I launched one of my own SaaS products and watched real users use it at scale, with over a thousand active users during peak hours, without the system crashing.</p>
<p>I’m sharing this because I’ve been where you are now.</p>
<p>If you continue reading, you will:</p>
<ul>
<li><p>Learn from real experience building applications used by real users</p>
</li>
<li><p>Learn what not to do, based on years of mistakes and lessons</p>
</li>
<li><p>Learn what actually works and what helps you stand out as a junior developer</p>
</li>
<li><p>Clear up common misconceptions that slow people down</p>
</li>
</ul>
<p>This article is not about theory. It’s about building real things.</p>
<p>To drive this point home, we’ll build a real world application that solves a real problem and is used by real people. Along the way, you’ll learn how to come up with real application ideas, how to build them with simple tools, and how to serve them to many users.</p>
<p>If this sounds like something you’re up for, then let’s get started.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-you-probably-think-you-dont-know-enough">You Probably Think You Don’t Know Enough</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-find-real-world-application-ideas">How to Find Real World Application Ideas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What Are We Going to Build</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-1-setting-up-the-backend">Step 1: Setting Up the Backend</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-adding-background-removal-to-the-backend">Step 2: Adding Background Removal to the Backend</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-building-the-frontend">Step 3: Building the Frontend</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-running-and-testing-the-application-locally">Running and Testing the Application Locally</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-putting-the-backend-on-the-internet">Step 4: Putting the Backend on the Internet</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-deploying-the-backend-on-cloud-run">Deploying the Backend on Cloud Run</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-updating-the-frontend-to-use-the-live-backend">Updating the Frontend to Use the Live Backend</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-making-the-backend-and-frontend-work-together-cors">Step 5: Making the Backend and Frontend Work Together CORS</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-putting-the-frontend-on-the-internet">Step 6: Putting the Frontend on the Internet</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts-what-you-just-built-matters">Final Thoughts What You Just Built Matters</a></p>
</li>
</ol>
<h2 id="heading-you-probably-think-you-dont-know-enough"><strong>You Probably Think You Don't Know Enough</strong></h2>
<p>Before we begin, I want to clear up the most common misconception beginners have.</p>
<p>Many developers believe they don’t know enough to start building real world applications. They think they need to learn more JavaScript, more Python, or another framework before they are ready. Some even think learning React is the final step that will suddenly make everything click.</p>
<p>This belief is very common, but it’s not true.</p>
<p>If you know how to write HTML, CSS, and a simple loop or function in any programming language, you already have most of what it takes to build a real world application. This tutorial is proof of that.</p>
<p>That’s why I am writing this article. Not to tell you to learn more first, but to show you how far you can go with what you already know.</p>
<h2 id="heading-how-to-find-real-world-application-ideas">How to Find Real World Application Ideas</h2>
<p>One question beginners ask a lot is, “What kind of apps should I build?”</p>
<p>This is rarely talked about, but it matters more than most people think.</p>
<p>A simple rule is this: build things that already exist.</p>
<p>Look at the apps you use every day, especially the simple ones. Tools that do one thing well. If you find yourself using an app often, that app is solving a real problem.</p>
<p>For example, people use background removers to clean up images. They use URL shorteners to share links. They use notes apps to save quick thoughts. None of these ideas are new, but they are real.</p>
<p>You don’t need to invent something original. You need to understand a problem and build a working solution for it.</p>
<p>When you replicate real tools, you naturally learn how real applications are structured. You also end up with projects that make sense on a résumé, because they solve problems people recognize.</p>
<p>That’s exactly what we are going to do in this tutorial.</p>
<h2 id="heading-what-are-we-going-to-build">What Are We Going to Build?</h2>
<p>I’ll tell you now, it is not going to be another Hello World application. We’re going to be building a background remover web application.</p>
<p>This is the kind of tool people actually use. Designers use it for images, content creators use it for thumbnails, and developers build similar features into real products. It works with real files, real data, and real results.</p>
<p>If you want to see the final result before we start building, you can try the working app here: <a target="_blank" href="https://iamspruce.github.io/background-remover/">https://iamspruce.github.io/background-remover/</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769502551999/c2bdf45f-8768-4dc8-a816-6fa9a05dc15b.png" alt="The background remover application we are about to build" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>We’ll build this app using simple tools on purpose. Plain HTML, CSS, and JavaScript for the frontend, and Python for the backend. No heavy frameworks and no complicated setup.</p>
<p>Before we continue, let me clear up <strong>another common misconception.</strong></p>
<p>Many developers believe that for an application to be taken seriously, it must be built with complex frameworks. In my experience building applications for clients around the world over the last 10 years, not a single client has ever asked me what framework I used.</p>
<p>They only cared about one thing: Did it work, and did it solve their problem?</p>
<p>Users won’t care how your app is built. They care that it works. If HTML, CSS, and JavaScript can solve the problem, there’s no reason to wait months just to learn a new framework.</p>
<p>Now that we understand <em>why</em> we’re building this app and <em>what</em> problem it solves, it’s time to start writing code.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we start writing code, let’s quickly talk about what you need.</p>
<p>This tutorial is not for absolute beginners, but it’s also not super advanced. If you’ve built small things before and you want to build something that actually feels real, you’re in the right place.</p>
<h3 id="heading-what-you-should-already-know">What You Should Already Know</h3>
<p>You should be comfortable with:</p>
<ul>
<li><p>Basic HTML: You know what inputs, buttons, images, and divs do.</p>
</li>
<li><p>Basic CSS: You can style a page and make it look presentable.</p>
</li>
<li><p>Basic JavaScript: You know how to listen for a button click and send a request using <code>fetch</code>.</p>
</li>
</ul>
<p>That’s enough to follow along.</p>
<p>You don’t need React or any other frontend framework.</p>
<h3 id="heading-backend-knowledge">Backend Knowledge</h3>
<p>For the backend, you don’t need to be a Python expert.</p>
<p>You just need to understand that:</p>
<ul>
<li><p>Python can run a server</p>
</li>
<li><p>A server can receive requests</p>
</li>
<li><p>A server can send back responses</p>
</li>
</ul>
<p>Everything else will be explained as we go.</p>
<h3 id="heading-tools-you-need">Tools You Need</h3>
<p>Make sure you have these installed:</p>
<ul>
<li><p>Python 3.9 or newer</p>
</li>
<li><p>Git</p>
</li>
<li><p>A code editor like VS Code</p>
</li>
<li><p>A browser</p>
</li>
</ul>
<p>No Docker knowledge or cloud experience required.</p>
<h3 id="heading-github-account-important">GitHub Account (Important)</h3>
<p>We’ll deploy the backend directly from GitHub, so you’ll need a GitHub account.</p>
<p>If you’ve never pushed a project to GitHub or hosted one before, I’ve already written a <a target="_blank" href="https://www.freecodecamp.org/news/host-your-first-project-on-github/">beginner-friendly guide</a> you can follow first.</p>
<p>Read that article, then come back here.</p>
<h3 id="heading-a-quick-mindset-check">A Quick Mindset Check</h3>
<p>This is not a copy-paste tutorial. You will see real errors. Things may break. That’s normal. That’s how real applications are built.</p>
<p>Now that we’re clear on what you need, let’s start writing code.</p>
<p>We’ll begin with the backend. This is an important decision, so let’s explain it properly.</p>
<h2 id="heading-step-1-setting-up-the-backend">Step 1: Setting Up the Backend</h2>
<h3 id="heading-what-is-a-backend-and-why-do-we-need-one">What Is a Backend and Why Do We Need One?</h3>
<p>A backend is a program that runs on a server and does the heavy work for an application.</p>
<p>In our case, the heavy work is image processing. Removing a background from an image requires libraries that can’t run inside the browser. Browsers are designed for safety and user interaction, not for this kind of processing.</p>
<p>That’s why we need a backend.</p>
<p>The backend will:</p>
<ul>
<li><p>Receive an image from the user</p>
</li>
<li><p>Remove the background</p>
</li>
<li><p>Send the processed image back</p>
</li>
</ul>
<p>The frontend will simply talk to this backend later.</p>
<h3 id="heading-keeping-things-simple-on-purpose">Keeping Things Simple on Purpose</h3>
<p>Because this might be your first real project, we’re going to keep the backend as simple as possible.</p>
<ul>
<li><p>One programming language (Python)</p>
</li>
<li><p>One backend file</p>
</li>
<li><p>No complex folder structure</p>
</li>
<li><p>No advanced concepts</p>
</li>
</ul>
<p>This is intentional. Real world applications don’t have to start out complex. They typically start small and grow.</p>
<h3 id="heading-project-structure">Project Structure</h3>
<p>Create a new folder called:</p>
<pre><code class="lang-bash">background-remover
</code></pre>
<p>Inside it, create a folder for the backend:</p>
<pre><code class="lang-bash">background-remover/
  backend/
</code></pre>
<p>Move into the backend folder:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> background-remover/backend
</code></pre>
<p>Now create a virtual environment:</p>
<pre><code class="lang-bash">python -m venv env
</code></pre>
<p>A virtual environment keeps this project’s dependencies separate from everything else on your computer. This is standard practice and something you’ll see in real projects.</p>
<p>Now activate it:</p>
<p>macOS or Linux:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> env/bin/activate
</code></pre>
<p>Windows:</p>
<pre><code class="lang-bash">env\Scripts\activate
</code></pre>
<p>Now create a folder for your application code:</p>
<pre><code class="lang-bash">mkdir api
</code></pre>
<p>Your structure should now look like this:</p>
<pre><code class="lang-bash">background-remover/
  backend/
    env/
    api/
</code></pre>
<p>At this stage, nothing looks impressive yet. That’s normal.</p>
<h3 id="heading-installing-fastapi">Installing FastAPI</h3>
<p>We’ll use FastAPI to build the backend API.</p>
<p>Install it together with Uvicorn, which is the server that runs our app:</p>
<pre><code class="lang-bash">pip install fastapi uvicorn
</code></pre>
<p>FastAPI allows us to define endpoints clearly and with very little code, which is perfect for us.</p>
<h3 id="heading-creating-the-first-backend-file">Creating the First Backend File</h3>
<p>Inside the <code>api</code> folder, create a file called <code>main.py</code>.</p>
<p>Add the following code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI

app = FastAPI()

<span class="hljs-meta">@app.get("/health")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">health</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"status"</span>: <span class="hljs-string">"ok"</span>}
</code></pre>
<p>Let’s pause and understand what this does.</p>
<ul>
<li><p>We created a FastAPI application</p>
</li>
<li><p>We added a <code>/health</code> endpoint</p>
</li>
<li><p>This endpoint simply returns a message</p>
</li>
</ul>
<p>Before building real features, developers always confirm that their server actually runs. That is exactly what this endpoint is for.</p>
<h3 id="heading-running-the-server">Running the Server</h3>
<p>From inside the <code>backend</code> folder, start the server:</p>
<pre><code class="lang-bash">uvicorn api.main:app --reload
</code></pre>
<p>Now open a new terminal and run:</p>
<pre><code class="lang-bash">curl http://localhost:8000/health
</code></pre>
<p>You should see:</p>
<pre><code class="lang-bash">{<span class="hljs-string">"status"</span>:<span class="hljs-string">"ok"</span>}
</code></pre>
<p>This is an important moment.</p>
<p>You now have:</p>
<ul>
<li><p>A running backend server</p>
</li>
<li><p>A real HTTP endpoint</p>
</li>
<li><p>A response coming from your own code</p>
</li>
</ul>
<p>This is how real backend services start.</p>
<h3 id="heading-why-we-did-this-first">Why We Did This First</h3>
<p>At this point, you might wonder why we didn’t jump straight into background removal.</p>
<p>The reason is simple: if the server doesn’t run, nothing else matters.</p>
<p>By starting with a health endpoint, we removed uncertainty. We know the server works. Everything we add next is built on top of something we already know is working.</p>
<p>Now that the foundation is in place, we can move on to the real feature.</p>
<h2 id="heading-step-2-adding-background-removal-to-the-backend">Step 2: Adding Background Removal to the Backend</h2>
<p>Before we write any code here, we need to clear up an important misconception.</p>
<h3 id="heading-a-common-misconception-about-machine-learning">A Common Misconception About Machine Learning</h3>
<p>When people hear “background removal,” they often think machine learning is too advanced for them.</p>
<p>In real world development, this is almost never how it works.</p>
<p>You aren’t expected to build machine learning models yourself. You use libraries created by others and focus on integrating them correctly.</p>
<p>That is exactly what we’re doing here.</p>
<h3 id="heading-installing-the-background-removal-library">Installing the Background Removal Library</h3>
<p>Install the required packages:</p>
<pre><code class="lang-bash">pip install rembg pillow onnxruntime
</code></pre>
<ul>
<li><p><code>rembg</code> handles the background removal</p>
</li>
<li><p><code>pillow</code> helps us work with images</p>
</li>
</ul>
<p>For our purposes here, you don’t need to understand how these libraries work internally. You only need to know how to use them.</p>
<h3 id="heading-adding-the-background-removal-endpoint">Adding the Background Removal Endpoint</h3>
<p>Now update <code>main.py</code> so it looks like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, UploadFile, File
<span class="hljs-keyword">from</span> rembg <span class="hljs-keyword">import</span> remove
<span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image
<span class="hljs-keyword">import</span> io

app = FastAPI()

<span class="hljs-meta">@app.get("/health")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">health</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"status"</span>: <span class="hljs-string">"ok"</span>}

<span class="hljs-meta">@app.post("/remove-bg")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">remove_bg</span>(<span class="hljs-params">file: UploadFile = File(<span class="hljs-params">...</span>)</span>):</span>
    image_bytes = <span class="hljs-keyword">await</span> file.read()
    image = Image.open(io.BytesIO(image_bytes))

    output = remove(image)

    buffer = io.BytesIO()
    output.save(buffer, format=<span class="hljs-string">"PNG"</span>)
    buffer.seek(<span class="hljs-number">0</span>)

    <span class="hljs-keyword">return</span> buffer.getvalue()
</code></pre>
<p>Let’s explain this carefully.</p>
<ul>
<li><p>The endpoint accepts an uploaded image</p>
</li>
<li><p>The image is read into memory</p>
</li>
<li><p>The background is removed</p>
</li>
<li><p>The result is saved as a PNG with transparency</p>
</li>
<li><p>The image is returned to the client</p>
</li>
</ul>
<p>This endpoint is the core of our application.</p>
<h3 id="heading-testing-the-endpoint-with-curl">Testing the Endpoint With curl</h3>
<p>Before building the frontend, we’ll test the backend directly.</p>
<p>Run this command:</p>
<pre><code class="lang-javascript">curl -X POST \
  -F <span class="hljs-string">"file=@person.jpg"</span> \
  <span class="hljs-attr">http</span>:<span class="hljs-comment">//localhost:8000/remove-bg \</span>
  --output result.png
</code></pre>
<p>Open <code>result.png</code>. If you see the background removed, then the backend is complete.</p>
<p>At this point, you have built a backend that:</p>
<ul>
<li><p>Accepts real user input</p>
</li>
<li><p>Processes real data</p>
</li>
<li><p>Returns a meaningful result</p>
</li>
</ul>
<p>This is a real backend.</p>
<h3 id="heading-where-we-are-now">Where We Are Now</h3>
<p>Let’s pause and summarize:</p>
<ul>
<li><p>We set up a backend server</p>
</li>
<li><p>We confirmed that it runs</p>
</li>
<li><p>We added a real feature</p>
</li>
<li><p>We tested it without a frontend</p>
</li>
</ul>
<p>This is exactly how real developers work.</p>
<p>In the next section, we’ll build a simple frontend that talks to this backend and turns it into something users can interact with.</p>
<h2 id="heading-step-3-building-the-frontend-what-the-user-actually-sees">Step 3: Building the Frontend (What the User Actually Sees)</h2>
<p>At this point, our backend is working.</p>
<p>It can receive an image, remove the background, and send the result back. But right now, only developers can use it, because it requires terminal commands.</p>
<p>To make this useful to actual (non-technical) people, we need a frontend.</p>
<p>The frontend is simply the part of the application users see and interact with in their browser.</p>
<h3 id="heading-clearing-a-common-misconception-about-frontends">Clearing a Common Misconception About Frontends</h3>
<p>Many beginners think building a frontend means learning a framework first.</p>
<p>This is not true.</p>
<p>Frameworks help later, but they aren’t required to build real applications. Under the hood, every frontend still comes down to HTML, CSS, and JavaScript.</p>
<p>That’s why we are using plain HTML, CSS, and JavaScript here. No React, no build tools, no setup. Just the basics.</p>
<h3 id="heading-what-our-frontend-will-do">What Our Frontend Will Do</h3>
<p>Our frontend has one job. It will:</p>
<ul>
<li><p>Let the user select an image</p>
</li>
<li><p>Send that image to the backend</p>
</li>
<li><p>Receive the processed image</p>
</li>
<li><p>Show it on the screen</p>
</li>
<li><p>Allow the user to download it</p>
</li>
</ul>
<p>That’s all.</p>
<p>If it does these things correctly, it’s a real frontend.</p>
<h3 id="heading-creating-the-frontend">Creating the Frontend</h3>
<p>Go back to the root of your project and create three files:</p>
<pre><code class="lang-bash">index.html
styles.css
app.js
</code></pre>
<p>This simple setup is very common. Each file has a clear responsibility, which makes the code easier to understand.</p>
<h3 id="heading-writing-the-html-page">Writing the HTML Page</h3>
<p>Open <code>index.html</code> and add the following:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Background Remover<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"styles.css"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Background Remover<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"imageInput"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"removeBtn"</span>&gt;</span>Remove Background<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"result"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"resultImage"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"downloadLink"</span> <span class="hljs-attr">download</span>&gt;</span>Download Image<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"app.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Right now, this page won’t do anything interesting. That’s expected.</p>
<p>HTML only describes what should be on the page. The behavior comes from JavaScript, which we’ll add after we add some styling.</p>
<h3 id="heading-adding-some-basic-styling">Adding Some Basic Styling</h3>
<p>Open <code>styles.css</code> and add this:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: sans-serif;
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">600px</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">40px</span> auto;
}

<span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.result</span> {
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-id">#downloadLink</span> {
  <span class="hljs-attribute">display</span>: none;
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<p>This is not about making things look fancy.</p>
<p>The goal here is simply to make the page readable and pleasant to use. Many real internal tools look no better than this. (And you can always improve the styling later if you want.)</p>
<h3 id="heading-connecting-the-frontend-to-the-backend">Connecting the Frontend to the Backend</h3>
<p>Now we’ll write the JavaScript that makes everything work.</p>
<p>Open <code>app.js</code> and add the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> imageInput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"imageInput"</span>);
<span class="hljs-keyword">const</span> removeBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"removeBtn"</span>);
<span class="hljs-keyword">const</span> resultImage = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"resultImage"</span>);
<span class="hljs-keyword">const</span> downloadLink = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"downloadLink"</span>);

removeBtn.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> file = imageInput.files[<span class="hljs-number">0</span>];

  <span class="hljs-keyword">if</span> (!file) {
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-keyword">const</span> formData = <span class="hljs-keyword">new</span> FormData();
  formData.append(<span class="hljs-string">"file"</span>, file);

  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:8000/remove-bg"</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
    <span class="hljs-attr">body</span>: formData,
  });

  <span class="hljs-keyword">const</span> blob = <span class="hljs-keyword">await</span> response.blob();
  <span class="hljs-keyword">const</span> imageUrl = URL.createObjectURL(blob);

  resultImage.src = imageUrl;
  downloadLink.href = imageUrl;
  downloadLink.style.display = <span class="hljs-string">"inline"</span>;
});
</code></pre>
<p>Let’s slow down and explain what’s happening here:</p>
<ul>
<li><p>We read the image selected by the user</p>
</li>
<li><p>We wrap it in <code>FormData</code> so it can be sent to the backend</p>
</li>
<li><p>We send it to our <code>/remove-bg</code> endpoint</p>
</li>
<li><p>We receive the processed image back</p>
</li>
<li><p>We display it and prepare it for download</p>
</li>
</ul>
<p>This is the moment where the frontend and backend finally talk to each other.</p>
<h3 id="heading-running-the-frontend-with-live-server">Running the Frontend With Live Server</h3>
<p>Before testing, make sure your backend is still running.</p>
<p>Now, instead of opening <code>index.html</code> directly, use the <strong>Live Server</strong> extension in VS Code.</p>
<p>If you don’t have it installed, just open VS Code extensions, search for “Live Server”, and then install it. Then right click on <code>index.html</code> and click “Open with Live Server”.</p>
<p>This starts a small local server for the frontend.</p>
<p>Why does this matter?</p>
<p>Many browser features work better when files are served through a server instead of opened directly from the file system. Using Live Server also matches how real frontends are served.</p>
<h3 id="heading-testing-the-full-application-locally">Testing the Full Application Locally</h3>
<p>Now choose an image and click the button.</p>
<p>If everything is working:</p>
<ul>
<li><p>The image is sent to the backend</p>
</li>
<li><p>The background is removed</p>
</li>
<li><p>The result appears on the page</p>
</li>
<li><p>The download link shows up</p>
</li>
</ul>
<p>Take a moment here. You have just built:</p>
<ul>
<li><p>A backend that processes real data</p>
</li>
<li><p>A frontend that talks to it</p>
</li>
<li><p>A complete application running locally</p>
</li>
</ul>
<p>This is already more than a “Hello World” project.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769503437045/6a984e58-cee9-4255-84aa-76ee26b805b3.png" alt="The application running locally after connecting the frontend and backend and removing background from an image" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-clearing-one-more-misconception">Clearing One More Misconception</h3>
<p>Some beginners look at this and think: “This feels too simple to be a real app.”</p>
<p>This is another misconception. Real applications aren’t defined by complexity. They’re defined by usefulness. If your app solves a real problem and people can use it, it’s a real application.</p>
<p>In the next section, we’ll take this exact app and put it on the internet so anyone can use it.</p>
<h2 id="heading-step-4-putting-the-backend-on-the-internet">Step 4: Putting the Backend on the Internet</h2>
<p>Right now, your backend is running on your computer.</p>
<p>That means:</p>
<ul>
<li><p>It works only for you</p>
</li>
<li><p>If you close your laptop, it stops</p>
</li>
<li><p>If someone opens your frontend, it cannot reach your backend</p>
</li>
</ul>
<p>To fix this, we need to run the backend on a computer that is <strong>always online</strong>.</p>
<p>This process is called <strong>deployment</strong>.</p>
<h3 id="heading-a-simple-way-to-think-about-deployment">A Simple Way to Think About Deployment</h3>
<p>Deployment does <strong>not</strong> mean writing new code.</p>
<p>It simply means this: instead of running your backend on your laptop, you run it on another computer that never sleeps.</p>
<p>Everything we do next exists only to make that happen.</p>
<h3 id="heading-why-we-arent-using-netlify-or-vercel">Why We Aren’t Using Netlify or Vercel</h3>
<p>You might be wondering why we aren’t using Netlify or Vercel. Those platforms are great, but they’re mainly for <strong>frontends</strong>.</p>
<p>They work best when your app is:</p>
<ul>
<li><p>Static HTML, CSS, and JavaScript</p>
</li>
<li><p>A frontend framework like React or Vue</p>
</li>
<li><p>Small serverless functions</p>
</li>
</ul>
<p>Our backend is different. It’s a <strong>Python server</strong> that:</p>
<ul>
<li><p>Stays running</p>
</li>
<li><p>Accepts image uploads</p>
</li>
<li><p>Processes images</p>
</li>
<li><p>Uses heavy native libraries for background removal</p>
</li>
</ul>
<p>This kind of backend needs a <strong>real server</strong>, not a lightweight serverless function.</p>
<p>That’s why Netlify and Vercel aren’t a good fit here.</p>
<h3 id="heading-why-were-using-cloud-run">Why We’re Using Cloud Run</h3>
<p>Instead, we’re using <strong>Cloud Run</strong>.</p>
<p>Cloud Run lets us run real backend servers on Google’s infrastructure without managing servers ourselves.</p>
<p>We’re using it because:</p>
<ul>
<li><p>It supports full Python backends</p>
</li>
<li><p>It deploys directly from GitHub</p>
</li>
<li><p>It handles scaling and servers for us</p>
</li>
<li><p>It works well with heavy workloads</p>
</li>
<li><p>It’s beginner-friendly</p>
</li>
</ul>
<p>Most importantly, it lets you deploy a <strong>real backend</strong> without learning cloud commands or CI/CD pipelines.</p>
<h3 id="heading-preparing-the-backend-for-cloud-run">Preparing the Backend for Cloud Run</h3>
<p>Before deploying, we need to make sure our backend is ready.</p>
<h4 id="heading-creating-requirementstxt">Creating <code>requirements.txt</code></h4>
<p>Inside the <code>backend</code> folder, create a file called <code>requirements.txt</code>.</p>
<p>Add this:</p>
<pre><code class="lang-go">fastapi
uvicorn
rembg
pillow
onnxruntime
</code></pre>
<p>This file tells Cloud Run which Python libraries to install.</p>
<h3 id="heading-creating-a-github-repository">Creating a GitHub Repository</h3>
<p>Cloud Run deploys directly from GitHub, so our code must live there.</p>
<p>From the project root, run:</p>
<pre><code class="lang-go">git init
git add .
git commit -m <span class="hljs-string">"Initial background remover project"</span>
git branch -M main
git remote add origin YOUR_REPO_URL
git push -u origin main
</code></pre>
<p>This <strong>single repository</strong> will be used for both backend and frontend.</p>
<h3 id="heading-deploying-the-backend-on-cloud-run">Deploying the Backend on Cloud Run</h3>
<p>Now open your browser and go to <strong>Google Cloud Console</strong>.</p>
<h4 id="heading-1-create-a-new-project">1. Create a New Project</h4>
<p>Open <a target="_blank" href="https://console.cloud.google.com">Google Cloud Console</a> and click New Project. Give it a name (for example: <code>background-remover</code>) and then click Create.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769749541636/778464de-2c95-4f7e-9505-9729a84f2001.png" alt="Creating a new Google Cloud project" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-2-open-cloud-run">2. Open Cloud Run</h4>
<p>Use the search bar at the top and search for <strong>Cloud Run.</strong> Then open it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769749581066/9078ae2e-fa00-4dfa-be04-383d9702bb90.png" alt="Cloud Run overview page" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Cloud Run will automatically enable the required APIs.</p>
<p>You will be asked to set up billing. Google gives you $300 free credit, which is more than enough for this tutorial.</p>
<h4 id="heading-3-start-creating-the-service">3. Start Creating the Service</h4>
<p>Click Create Service and choose Deploy continuously from a repository.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769749636809/348f720a-b1b1-46e4-9eab-48928adeb2f3.png" alt="Creating a Cloud Run service from a repository" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-4-connect-your-github-account">4. Connect Your GitHub Account</h4>
<p>Select <strong>GitHub</strong> as the repository provider and authenticate your GitHub account. Then install Google Cloud Build on your GitHub account. Choose <strong>only the repository</strong> you want to deploy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769749686780/89571b5e-0bd7-4127-82d2-b9445a5044e4.png" alt="Installing Google Cloud Build on GitHub" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>This allows Google Cloud to build and deploy your code automatically.</p>
<h4 id="heading-5-select-the-repository">5. Select the Repository</h4>
<p>Then choose the repository you just installed Cloud Build on and select the <code>main</code> branch.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769749745522/a9f95c4b-7fd3-480d-bae1-7ae92bcdd52f.png" alt="Selecting the GitHub repository" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-6-configure-the-build">6. Configure the Build</h4>
<p>Now comes the important part: building the context directory.</p>
<p>Set this to:</p>
<pre><code class="lang-bash">backend
</code></pre>
<p>This tells Cloud Run:</p>
<blockquote>
<p>“My backend code lives inside the <code>backend</code> folder.”</p>
</blockquote>
<p>For the entry command, enter:</p>
<pre><code class="lang-bash">uvicorn api.main:app --host 0.0.0.0 --port 8080
</code></pre>
<p>This is how Cloud Run starts your FastAPI server.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769749801126/87676cce-3e75-4244-b32f-401f782d7c85.png" alt="Build configuration for the backend" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-7-configure-container-resources">7. Configure Container Resources</h4>
<p>Our backend runs a <strong>background-removal model</strong>, which is heavy.</p>
<p>So we must increase resources.</p>
<ul>
<li><p>Change memory from <strong>512 MB → 2 GB</strong></p>
</li>
<li><p>Set CPU to <strong>4</strong></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769749870471/a24e5d37-af21-48a6-b720-b6748d478b6d.png" alt="Increasing memory and CPU" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>This ensures the model can load and run properly.</p>
<h4 id="heading-8-deploy">8. Deploy</h4>
<p>Now click <strong>Create</strong>.</p>
<p>Cloud Run will:</p>
<ul>
<li><p>Build your app</p>
</li>
<li><p>Install dependencies</p>
</li>
<li><p>Create a container</p>
</li>
<li><p>Deploy it to the internet</p>
</li>
</ul>
<p>You’ll see logs showing the build and deployment process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769749916316/5eb276f6-01c1-413c-aeb7-13a8d34dbbe2.png" alt="Cloud Build running" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>This can take a few minutes. That’s normal.</p>
<h3 id="heading-checking-that-the-backend-is-live">Checking That the Backend Is Live</h3>
<p>Once deployment finishes, Cloud Run will show you a <strong>public URL</strong>.</p>
<p>Test it:</p>
<pre><code class="lang-bash">curl https://YOUR_CLOUD_RUN_URL/health
</code></pre>
<p>If you see:</p>
<pre><code class="lang-bash">{<span class="hljs-string">"status"</span>:<span class="hljs-string">"ok"</span>}
</code></pre>
<p>Your backend is officially live on the internet.</p>
<p>Pause here for a second.</p>
<p>You just deployed a real backend. Congratulations.</p>
<h3 id="heading-updating-the-frontend-to-use-the-live-backend">Updating the Frontend to Use the Live Backend</h3>
<p>Open <code>app.js</code>.</p>
<p>Replace:</p>
<pre><code class="lang-bash">http://localhost:8000/remove-bg
</code></pre>
<p>With:</p>
<pre><code class="lang-bash">https://YOUR_CLOUD_RUN_URL/remove-bg
</code></pre>
<p>Save the file and reload the frontend.</p>
<h2 id="heading-step-5-making-the-backend-and-frontend-work-together"><strong>Step 5: Making the Backend and Frontend Work Together</strong></h2>
<p>At this point, we have two things:</p>
<ul>
<li><p>A backend running on the internet</p>
</li>
<li><p>A frontend running in the browser</p>
</li>
</ul>
<p>Now we want them to talk to each other.</p>
<p>Open your frontend, select an image, and click the button. You’ll notice that it still doesn’t work. This is expected.</p>
<h3 id="heading-what-is-happening-here">What Is Happening Here?</h3>
<p>Your frontend is running on one address, while your backend is running on another address.</p>
<p>Browsers are very strict about this. By default, a browser will block requests from one website to another unless the backend explicitly allows it. This is a security feature.</p>
<p>This rule is called <strong>CORS</strong>.</p>
<h3 id="heading-clearing-a-common-misconception-about-cors">Clearing a Common Misconception About CORS</h3>
<p>When beginners see a CORS error, they often think something is broken.</p>
<p>Nothing is broken. CORS is simply the browser saying: “I need the backend to confirm that this frontend is allowed to talk to it.”</p>
<p>So all we need to do is tell the backend: “It’s okay for requests to come from my frontend.”</p>
<h3 id="heading-allowing-only-our-frontend-not-everyone">Allowing Only Our Frontend (Not Everyone)</h3>
<p>Instead of allowing requests from everywhere, we’ll allow requests only from our frontend. This is a good habit to learn early.</p>
<p>Open <code>backend/api/main.py</code>.</p>
<p>Add this import at the top:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi.middleware.cors <span class="hljs-keyword">import</span> CORSMiddleware
</code></pre>
<p>Then, after creating the FastAPI app, add this:</p>
<pre><code class="lang-python">app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        <span class="hljs-string">"http://127.0.0.1:5500"</span>,
        <span class="hljs-string">"http://localhost:5500"</span>
    ],
    allow_methods=[<span class="hljs-string">"POST"</span>],
    allow_headers=[<span class="hljs-string">"*"</span>],
)
</code></pre>
<p>Why these URLs?</p>
<p>If you’re using the Live Server extension, your frontend is usually served on port <code>5500</code>. These are the addresses your browser is using locally.</p>
<p>We’re telling the backend: “Only accept requests from this frontend.”</p>
<p>That is exactly what we want.</p>
<h3 id="heading-redeploying-the-backend">Redeploying the Backend</h3>
<p>Any time you change backend code, you need to redeploy it.</p>
<p>Since our backend is deployed on Cloud Run and set up with automatic deploy, redeploying is simple, all you need to do is push your changes.</p>
<p>From the project root, run:</p>
<pre><code class="lang-go">git add .
git commit -m <span class="hljs-string">"Add CORS configuration"</span>
git push
</code></pre>
<p>Cloud Run will automatically detect the change and redeploy your backend.</p>
<p>Wait for the deployment to finish. Once it’s done, your backend will now allow requests from your local frontend.</p>
<h3 id="heading-testing-again">Testing Again</h3>
<p>Reload your frontend in the browser.</p>
<p>Select an image and click the button. This time, it should work.</p>
<p>You just handled a real browser security rule that every production app runs into. That alone is a huge learning step.</p>
<h2 id="heading-step-6-putting-the-frontend-on-the-internet-github-pages">Step 6: Putting the Frontend on the Internet (GitHub Pages)</h2>
<p>Right now, your frontend works only on your computer.</p>
<p>Just like the backend earlier, this means no one else can use it.</p>
<p>Let’s fix that.</p>
<h3 id="heading-why-github-pages">Why GitHub Pages?</h3>
<p>Our frontend is:</p>
<ul>
<li><p>Just HTML, CSS, and JavaScript</p>
</li>
<li><p>No backend code</p>
</li>
<li><p>No build step</p>
</li>
</ul>
<p>This makes it perfect for GitHub Pages. GitHub Pages can host static sites for free, and it’s very beginner friendly.</p>
<h3 id="heading-preparing-the-frontend-for-deployment">Preparing the Frontend for Deployment</h3>
<p>Make sure all your frontend files are inside the frontend folder:</p>
<pre><code class="lang-javascript">frontend/
  index.html
  styles.css
  app.js
</code></pre>
<p>Open app.js and make sure the backend URL is the Cloud Run URL, not localhost.</p>
<pre><code class="lang-javascript">fetch(<span class="hljs-string">"https://YOUR_CLOUD_RUN_URL/remove-bg"</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
  <span class="hljs-attr">body</span>: formData,
});
</code></pre>
<p>Save the file.</p>
<h3 id="heading-pushing-the-frontend-to-github">Pushing the Frontend to GitHub</h3>
<p>We already created a GitHub repository earlier, so we’ll reuse it.</p>
<p>From the project root, run:</p>
<pre><code class="lang-javascript">git add .
git commit -m <span class="hljs-string">"Add frontend and prepare for GitHub Pages"</span>
git push
</code></pre>
<h3 id="heading-enabling-github-pages">Enabling GitHub Pages</h3>
<ol>
<li><p>Go to your repository on GitHub.</p>
</li>
<li><p>Open Settings.</p>
</li>
<li><p>Click Pages.</p>
</li>
</ol>
<p>Under Source, select:</p>
<ol>
<li><p>Branch: main</p>
</li>
<li><p>Folder: /(root)</p>
</li>
</ol>
<p>Save everything. After a few seconds, GitHub will give you a URL. This URL is now your frontend on the internet.</p>
<h3 id="heading-updating-cors-for-the-live-frontend">Updating CORS for the Live Frontend</h3>
<p>Now that the frontend is live, go back to backend/api/main.py.</p>
<p>Replace the local origins with your GitHub Pages URL:</p>
<pre><code class="lang-python">allow_origins=[
    <span class="hljs-string">"https://YOUR_GITHUB_USERNAME.github.io"</span>
]
</code></pre>
<p>Commit and push the change:</p>
<pre><code class="lang-bash">git add .
git commit -m <span class="hljs-string">"Update CORS for GitHub Pages"</span>
git push
</code></pre>
<p>Cloud Run will redeploy the backend automatically.</p>
<h3 id="heading-final-test">Final Test</h3>
<p>Open your GitHub Pages URL.</p>
<p>Upload an image, remove the background, and download the result.</p>
<p>Everything is now live.</p>
<h2 id="heading-where-you-are-now">Where You Are Now</h2>
<p>Let’s be very clear about what you just did.</p>
<p>You:</p>
<ul>
<li><p>Built a real backend</p>
</li>
<li><p>Deployed it to the internet</p>
</li>
<li><p>Built a frontend</p>
</li>
<li><p>Deployed it to the internet</p>
</li>
<li><p>Fixed real production issues</p>
</li>
<li><p>Connected everything properly</p>
</li>
</ul>
<p>This is not a demo project. This is a real application.</p>
<p>In the final section, we’ll wrap things up, talk about what you learned, and where you can go next.</p>
<h2 id="heading-final-thoughts-what-you-just-built-matters">Final Thoughts: What You Just Built Matters</h2>
<p>At this point, it is worth stopping and looking back at what you have actually done.</p>
<p>You didn’t just follow steps. You didn’t just copy code. You built a real application.</p>
<h3 id="heading-lets-be-clear-about-what-you-accomplished">Let’s Be Clear About What You Accomplished</h3>
<p>You started with nothing more than basic tools and ideas.</p>
<p>By the end of this tutorial, you:</p>
<ul>
<li><p>Built a backend that processes real data</p>
</li>
<li><p>Used a machine learning tool without fear or overthinking</p>
</li>
<li><p>Exposed a backend to the internet</p>
</li>
<li><p>Built a frontend with plain HTML, CSS, and JavaScript</p>
</li>
<li><p>Connected the frontend and backend properly</p>
</li>
<li><p>Deployed both parts so real users can access them</p>
</li>
</ul>
<p>This is exactly how real applications are built, just at a smaller and more manageable scale.</p>
<h3 id="heading-why-this-is-no-longer-a-beginner-project">Why This Is No Longer a “Beginner Project”</h3>
<p>Many projects are called beginner projects, but they stop at showing things on a screen.</p>
<p>This one does not.</p>
<p>Your app:</p>
<ul>
<li><p>Accepts real input</p>
</li>
<li><p>Performs real work</p>
</li>
<li><p>Runs on real servers</p>
</li>
<li><p>Handles real browser rules</p>
</li>
<li><p>Can be shared with anyone</p>
</li>
</ul>
<p>That is the difference between learning syntax and building software.</p>
<h3 id="heading-the-most-important-lesson-in-this-tutorial">The Most Important Lesson in This Tutorial</h3>
<p>The most important thing you should take away from this is not the project you built.</p>
<p>It is this: You didn’t need to “know more” before you started.</p>
<p>You learned by building. You figured things out as they appeared. You fixed problems when they showed up.</p>
<p>That is how experience is gained. No one has experience before building real applications. No one lacks experience after building many of them.</p>
<h3 id="heading-what-you-can-do-next">What You Can Do Next</h3>
<p>This project isn’t the end. It’s a starting point.</p>
<p>Here are a few ideas you can explore next, using what you already know:</p>
<ul>
<li><p>Improve the user interface</p>
</li>
<li><p>Add loading states and better feedback</p>
</li>
<li><p>Restrict image size or file types</p>
</li>
<li><p>Add simple rate limiting</p>
</li>
<li><p>Build another small tool that solves a real problem</p>
</li>
</ul>
<p>You don’t need to jump to frameworks yet.</p>
<p>If you can build a few more projects like this, frameworks will make a lot more sense when you meet them.</p>
<h3 id="heading-one-last-thought">One Last Thought</h3>
<p>If this was your first real project, you should be proud of yourself.</p>
<p>You moved past tutorials, built something useful, and put it on the internet. That’s the line many developers never cross.</p>
<p>Now that you have crossed it, the next one will be easier.</p>
<p>So keep building!</p>
<h3 id="heading-source-code-and-live-demo">Source Code and Live Demo</h3>
<p>If you want to explore the full project or build on top of it, you can find everything here.</p>
<ul>
<li><p>Live application: <a target="_blank" href="https://iamspruce.github.io/background-remover/">https://iamspruce.github.io/background-remover/</a></p>
</li>
<li><p>GitHub repository: <a target="_blank" href="https://github.com/iamspruce/background-remover">https://github.com/iamspruce/background-remover</a></p>
</li>
</ul>
<p>If you have questions, reach me on X at <a target="_blank" href="https://x.com/sprucekhalifa"><code>@sprucekhalifa</code></a>. I write practical tech articles like this regularly.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The React Handbook for Beginners – JSX, Hooks, and Rendering Explained ]]>
                </title>
                <description>
                    <![CDATA[ React is one of the most powerful and widely used libraries for building user interfaces with JavaScript. From small components to large-scale front-end and full-stack applications, React gives you the flexibility to create interactive, efficient, an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-handbook-for-beginners-learn-jsx-hooks-rendering/</link>
                <guid isPermaLink="false">68f95319417d2ee394355b66</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Blogs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi Sofela ]]>
                </dc:creator>
                <pubDate>Wed, 22 Oct 2025 21:56:41 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761170169453/445fd0f5-54f9-4be5-bacf-2e6c6acd1f21.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>React is one of the most powerful and widely used libraries for building user interfaces with JavaScript. From small components to large-scale front-end and full-stack applications, React gives you the flexibility to create interactive, efficient, and modern features.</p>
<p>But learning React can feel overwhelming. With so many new terms, patterns, and frameworks like Next.js in the mix, it’s easy to feel lost.</p>
<p>That’s why this handbook focuses on React itself without unnecessary distractions. Once you’ve mastered React at its core, you’ll have the confidence to use it with or without frameworks to build anything you can imagine.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-you-should-already-know">What You Should Already Know</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-exactly-is-react">What Exactly Is React?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-the-react-name">Why the “React” name?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-is-react-a-framework">Is React a framework?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-is-react-only-for-web-development">Is React only for web development?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-whats-the-primary-goal-of-react">What’s the primary goal of React?</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-a-react-component-to-a-website">How to Add a React Component to a Website</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-create-a-new-project-directory">Create a new project directory</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-a-dom-container">Create a DOM container</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-import-react-babel-and-your-component">Import React, Babel, and your component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-your-component">Create your component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-configure-a-local-server">Configure a local server</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-jsx">What Is JSX?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-can-react-work-without-jsx">Can React work without JSX?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-1-create-a-react-element-with-jsx">Example 1: Create a React element with JSX</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-2-create-a-react-element-with-regular-javascript">Example 2: Create a React element with regular JavaScript</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-reactcreateelement">What Is React.createElement()?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-jsx">How to Use JSX</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-use-jsx-like-any-javascript-expression">Use JSX like any JavaScript expression</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrap-multi-line-jsx-in-parentheses">Wrap multi-line JSX in parentheses</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrap-expressions-in-curly-braces">Wrap expressions in curly braces</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-camelcase-to-name-attributes">Use camelCase to name attributes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-close-empty-jsx-tags-properly">Close empty JSX tags properly</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-react-component-can-return-only-a-single-element">A React component can return only a single element</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-time-to-practice-with-jsx">Time to Practice with JSX 🤸‍♂️🏋️‍♀️🏊‍♀️</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-the-solution">The solution</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-react-component">What Is a React Component?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-syntax-of-a-react-component">Syntax of a React component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-of-a-react-component">Example of a React component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-components-best-practices">React components best practices</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-render-lists-of-elements-from-an-array">How to Render Lists of Elements from an Array</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-each-react-element-in-an-array-needs-a-unique-key">Each React element in an array needs a unique key</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-unique-keys-to-each-react-element-in-an-array">How to add unique keys to each React element in an array</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-essential-things-to-know-about-assigning-keys">Essential things to know about assigning keys</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-handle-events-in-react">How to Handle Events in React</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-types-of-event-handlers">Types of event handlers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-inline-event-handler">Example: Inline event handler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-referenced-event-handler">Example: Referenced event handler</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-react-state">What Is React State?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-syntax-of-react-state">Syntax of React state</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-of-react-state">Example of React state</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-trigger-vs-render-vs-commit-vs-paint">React trigger vs render vs commit vs paint</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-does-it-mean-to-trigger-a-render-in-react">What does it mean to trigger a render in React?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-does-it-mean-to-render-react-components">What does it mean to render React components?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-does-it-mean-to-commit-a-react-ui-to-the-browsers-dom">What does it mean to commit a React UI to the browser’s DOM?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-does-it-mean-to-paint-the-dom-nodes-on-the-screen">What does it mean to paint the DOM nodes on the screen?</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-react-ref-hook">What Is the React Ref Hook?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-syntax-of-the-react-ref-hook">Syntax of the React ref Hook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-of-the-react-ref-hook">Example of the React ref Hook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-ref-hook-best-ractices">React ref Hook best practices</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-variables-vs-refs-vs-states-in-react">Variables vs Refs vs States in React</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-do-variables-work-in-react">How do variables work in React?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-do-refs-work-in-react">How do refs work in React?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-do-states-work-in-react">How do states work in React?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tips-on-using-variables-refs-and-states-in-react">Tips on using variables, refs, and states in React</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-useeffect-hook">What Is the useEffect Hook?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-syntax-of-the-useeffect-hook">Syntax of the useEffect Hook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-of-the-useeffect-hook">Example of the useEffect Hook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-useeffect-hooks-best-practices">useEffect Hook’s best practices</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-style-react-components">How to Style React Components</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-use-css-style-sheets-to-style-react-elements">How to use CSS style sheets to style React elements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-the-inline-style-attribute-to-style-react-elements">How to use the inline style attribute to style React elements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-css-modules-to-style-react-elements">How to use CSS Modules to style React elements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-a-css-in-js-library-to-style-react-elements">How to use a CSS-in-JS library to style React elements</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-overview">Overview</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-dive-deeper-into-react">Dive deeper into React</a></li>
</ul>
</li>
</ol>
<h2 id="heading-what-you-should-already-know">What You Should Already Know</h2>
<p>You will get the most value out of this handbook if you are familiar with:</p>
<ul>
<li><p>JavaScript fundamentals (variables, functions, arrays, objects)</p>
</li>
<li><p>Basic CSS for styling</p>
</li>
<li><p>HTML basics for structure</p>
</li>
</ul>
<p>If you’ve ever written a small JavaScript file or built a simple “Hello World” website, you are all set!</p>
<p>Let’s get started with the basics.</p>
<h2 id="heading-what-exactly-is-react">What Exactly Is React?</h2>
<p>React is a component-based JavaScript library for efficiently building user interfaces (UI).</p>
<p>No matter how massive or miniature your project may be, React is well-suited to help you develop any web application efficiently.</p>
<p>Developers primarily use React to build independent, reusable components that can be combined with other isolated user interfaces to create highly scalable applications. For instance, the image below illustrates the individual components of YouTube’s video player page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760577491945/1b0f8c61-b42e-4e3c-afdc-5804fdfa0d42.webp" alt="An Illustration of React Components. The YouTube video player page is illustrated as a combination of independent components." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In other words, React helps you build complex UIs from small, isolated components that can easily be reused in multiple applications. Each independent component tells React the exact element you want to display on screen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760577104799/4592a7d2-e75b-4ae6-b1f4-65cfd8e94033.webp" alt="React explained: The super flexible JavaScript library for modern frontend and full-stack app development" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The image above illustrates React as a highly adaptable library that uses JavaScript functions to build user interfaces for both mobile and web-based applications. Let’s discuss the points highlighted in the image.</p>
<h3 id="heading-why-the-react-name">Why the “React” name?</h3>
<p>The name stems from the idea that React renders your UI and reacts to events in the user interface it has rendered on screen.</p>
<h3 id="heading-is-react-a-framework">Is React a framework?</h3>
<p>No, React is a <a target="_blank" href="https://codesweetly.com/framework-vs-library/">library—not a framework</a>. React serves only as an add-on feature to your application. It’s not designed to be used as an app’s primary support system.</p>
<h3 id="heading-is-react-only-for-web-development">Is React only for web development?</h3>
<p>No, you don’t just use React on the web. For instance, ReactDOM helps build web applications, and React Native helps build mobile applications.</p>
<h3 id="heading-can-react-be-used-for-full-stack-applications">Can React be used for full-stack applications?</h3>
<p>Absolutely. React is super flexible. You can use it in simple HTML projects, integrate it into existing code, or build complex full-stack applications. Its adaptability makes it suitable for a wide variety of development scenarios.</p>
<h3 id="heading-whats-the-primary-goal-of-react">What’s the primary goal of React?</h3>
<p>React’s primary goal is for you to use JavaScript functions to return and manage the UI (HTML element) you want to render (display) on the screen. For instance, consider the following:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DonationUserInterface</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>☕ Buy me a coffee<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
}
</code></pre>
<p>The JavaScript function above is a React component that returns the UI (HTML button element) we want to display on screen and manage with React. In fact, let’s implement the <code>DonationUserInterface</code> component on a live website using only HTML and JavaScript – no frameworks.</p>
<h2 id="heading-how-to-add-a-react-component-to-a-website">How to Add a React Component to a Website</h2>
<p>Follow the steps below to add a donation UI component to a live HTML website.</p>
<h3 id="heading-create-a-new-project-directory">Create a new project directory</h3>
<pre><code class="lang-bash">mkdir codesweetly-donation-ui-001
</code></pre>
<p><strong>Note:</strong> You can use any name you prefer. In this guide, we’ll use <code>codesweetly-donation-ui-001</code> for demonstration.</p>
<p>Afterward, navigate to your project directory using the command line.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> path/to/codesweetly-donation-ui-001
</code></pre>
<h3 id="heading-create-a-dom-container">Create a DOM container</h3>
<p>To add a React component to a webpage, you first need to specify the section of the page where you want to insert the UI. So, create an HTML page:</p>
<pre><code class="lang-bash">touch index.html
</code></pre>
<p>Afterward, open the new file and add the following code:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-US"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>CodeSweetly Donation UI<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- A div container (the DOM node) created for React to manage --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"donation-ui"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The snippet above created a DOM node (<code>&lt;div&gt;</code> element), inside which we want React to display and manage a donation user interface. In other words, the <code>&lt;div&gt;</code> represents the website’s section you want React to manage.</p>
<p>Some notes:</p>
<ul>
<li><p>The <code>div</code>’s <code>id</code> attribute is the reference we’ll later use in a JavaScript file to find the container and tell React to insert a donation UI.</p>
</li>
<li><p>Although most developers use a <code>&lt;div&gt;</code> tag as the DOM container, you can use other HTML elements like the <code>&lt;main&gt;</code> tag.</p>
</li>
<li><p>You can have multiple DOM containers anywhere inside the <code>&lt;body&gt;</code> element.</p>
</li>
<li><p>A DOM container is usually left empty, as React will overwrite its content.</p>
</li>
</ul>
<h3 id="heading-import-react-babel-and-your-component">Import React, Babel, and your component</h3>
<p>Use script tags to load React, Babel, and your component into your project’s HTML page.</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-US"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>CodeSweetly Donation UI<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Load the React Library --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react@18/umd/react.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Load the ReactDOM API --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react-dom@18/umd/react-dom.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Load the Babel Compiler --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/@babel/standalone/babel.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"donation-ui"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Load your React component --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/babel"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"DonationUserInterface.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The snippet above uses the first three script tags to load React, ReactDOM, and Babel from unpkg.com.</p>
<p>At the same time, we use the fourth script tag to import our donation component (which we will create in the following section).</p>
<p>Some notes:</p>
<ul>
<li><p>The <code>react</code> package is a library containing React’s core functionality for creating React components.</p>
</li>
<li><p>The ReactDOM API provides the required methods to use React with the DOM.</p>
</li>
<li><p>Babel is a compiler that transforms React code into plain JavaScript, as browsers don’t understand React syntax by default.</p>
</li>
<li><p>The <code>type="text/babel"</code> attribute tells Babel to automatically execute and convert the <code>DonationUserInterface.js</code> script from React code into plain JavaScript.</p>
</li>
<li><p>The setup above is recommended for learning React only. Don’t use it for public projects (production environment). You can learn how to set up React for production in my <a target="_blank" href="https://www.amazon.com/dp/B0FRC4R8T3?tag=codesweetly00-20">Code React Sweetly book</a>.</p>
</li>
<li><p>The scripts will not work if your internet or <code>unpkg.com</code>’s server is down. So, if nothing renders on-screen, enter each script’s <code>src</code> URL in your browser to confirm if the server responds successfully.</p>
</li>
</ul>
<h3 id="heading-create-your-component">Create your component</h3>
<p>Create a <code>DonationUserInterface.js</code> JavaScript file inside the same folder in which your HTML file is located.</p>
<pre><code class="lang-bash">touch DonationUserInterface.js
</code></pre>
<p>Then, paste the following code inside the JavaScript file you’ve just created:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DonationUserInterface</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [donate, setDonate] = React.useState(<span class="hljs-literal">false</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUserInterface</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (donate) {
      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.buymeacoffee.com/codesweetly"</span>&gt;</span>Support page<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>.
          Thank you so much! 🎉
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
      );
    }
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setDonate(true)}&gt;☕ Buy me a coffee<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
  }
  <span class="hljs-keyword">return</span> createUserInterface();
}

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"donation-ui"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DonationUserInterface</span> /&gt;</span></span>);
</code></pre>
<p>The snippet above does the following:</p>
<ol>
<li><p>Defines a component named <code>DonationUserInterface</code>.</p>
</li>
<li><p>Initializes the component’s state (built-in object) with the Boolean value <code>false</code>.</p>
</li>
<li><p>Programs the component to return a paragraph element if the state’s <code>donate</code> variable is <code>true</code>. Otherwise, it should return a button element.</p>
</li>
<li><p>Creates a <code>ReactDOMRoot</code> object instance for the <code>donation-ui</code> HTML element you want React to manage. Afterwards, it assigns the newly created instance to the <code>root</code> variable.</p>
</li>
<li><p>Uses the object instance’s <code>render()</code> method to display the <code>DonationUserInterface</code> component inside the root <code>donation-ui</code>.</p>
</li>
</ol>
<h3 id="heading-configure-a-local-server">Configure a local server</h3>
<p>HTML files containing <a target="_blank" href="https://codesweetly.com/javascript-modules-tutorial/">ES modules</a> work only through <code>http://</code> and <code>https://</code> URLs, not locally via a <code>file://</code> URL.</p>
<p>Since we previously used the <code>type="text/babel"</code> attribute to convert the <code>DonationUserInterface.js</code> JavaScript file to an ES module, we need a local server, like “Live Server” or “Servor,” to load the HTML document via an <code>http://</code> scheme. Let’s install Servor so we can use it for this project.</p>
<h4 id="heading-install-the-servor-local-server">Install the Servor local server</h4>
<pre><code class="lang-bash">npm install servor@4.0.2 --save-dev
</code></pre>
<h4 id="heading-run-your-app">Run your app</h4>
<p>After installing Servor, use it to start your app from your terminal:</p>
<pre><code class="lang-bash">npx servor --browse --reload
</code></pre>
<p>Some notes:</p>
<ul>
<li><p>Close the server using <kbd>Ctrl</kbd> + <kbd>C</kbd> on Windows or <kbd>Cmd</kbd> + <kbd>C</kbd> on Mac.</p>
</li>
<li><p><code>--browse</code>: Opens the browser once the server starts.</p>
</li>
<li><p><code>--reload</code>: Reloads the browser whenever you update the project’s files.</p>
</li>
<li><p>You can also add the <code>servor</code> command to the <code>"scripts"</code> field of your project’s <code>package.json</code> file:</p>
</li>
</ul>
<pre><code class="lang-json">{
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"servor --browse --reload"</span>
  },
  <span class="hljs-attr">"devDependencies"</span>: {
    <span class="hljs-attr">"servor"</span>: <span class="hljs-string">"^4.0.2"</span>
  }
}
</code></pre>
<p>By doing so, you can run your app from your terminal like this:</p>
<pre><code class="lang-bash">npm run start
</code></pre>
<p>And that’s it! You’ve successfully added a React component to a live website using a JavaScript function to render a donation UI on screen! 🎉</p>
<p>Are you asking why we’re writing HTML inside JavaScript? Well, that HTML-like code is called JSX. Let’s learn about it.</p>
<h2 id="heading-what-is-jsx">What Is JSX?</h2>
<p>JSX is a JavaScript syntax extension that allows you to build React elements with HTML-like syntax directly inside your JavaScript code.</p>
<p><strong>Tips:</strong></p>
<ul>
<li><p>JSX is sometimes called JavaScript XML or JavaScript Syntax eXtension.</p>
</li>
<li><p>While JSX looks a lot like HTML, it’s not HTML. Instead, it enables you to use HTML-like syntax along with all the strengths of JavaScript.</p>
</li>
</ul>
<h3 id="heading-can-react-work-without-jsx">Can React work without JSX?</h3>
<p>Yes. React can work independently of JSX. But JSX makes it easier to create user interfaces (UI).</p>
<p>In other words, whatever you can do with JSX, you can do the same with plain JavaScript. For instance, consider the two examples below. The first includes JSX syntax, while the second is regular JavaScript syntax.</p>
<h4 id="heading-example-1-create-a-react-element-with-jsx">Example 1: Create a React element with JSX</h4>
<p><code>MyBio.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyBio</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My name is Oluwatobi.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
}
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MyBio</span> /&gt;</span></span>);
</code></pre>
<p><code>index.html</code></p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-US"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>MyBio App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react@18/umd/react.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react-dom@18/umd/react-dom.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/@babel/standalone/babel.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/babel"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"MyBio.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>In the React snippet above, <code>&lt;h1&gt;My name is Oluwatobi.&lt;/h1&gt;</code> and <code>&lt;MyBio /&gt;</code> are JSX.</p>
<p><strong>Tip:</strong> React supports the <code>.jsx</code> file extension for files with JSX code. So, if you prefer to differentiate your JSX files from JavaScript, you can rename <code>MyBio.js</code> to <code>MyBio.jsx</code>. Just note that choosing between using <code>.js</code> vs <code>.jsx</code> for files with JSX is entirely up to you. (Your JSX code is simply a syntactic sugar for the <code>React.createElement()</code> JavaScript call.)</p>
<h4 id="heading-example-2-create-a-react-element-with-regular-javascript">Example 2: Create a React element with regular JavaScript</h4>
<p><code>MyBio.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyBio</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> React.createElement(<span class="hljs-string">"h1"</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">"My name is Oluwatobi."</span>);
}
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(React.createElement(MyBio));
</code></pre>
<p><code>index.html</code></p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-US"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>MyBio App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react@18/umd/react.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react-dom@18/umd/react-dom.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/@babel/standalone/babel.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/babel"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"MyBio.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Everything in the React snippet above is plain JavaScript code.</p>
<h2 id="heading-what-is-reactcreateelement">What Is React.createElement()?</h2>
<p><code>React.createElement()</code> is the JavaScript alternative to JSX. It is a method for creating React elements in regular JavaScript.</p>
<p>Browsers can’t read the JSX syntax. This is why we typically use tools like Babel, TypeScript, and Parcel to compile JSX to a <code>React.createElement(component, props, ...children)</code> JavaScript call.</p>
<p>For instance, <code>&lt;button className="support-btn"&gt;Buy me a coffee&lt;/button&gt;</code> will transform to <code>React.createElement("button", { className: "support-btn" }, "Buy me a coffee ")</code> at runtime.</p>
<p>Under the hood, the <code>React.createElement()</code> method creates a JavaScript object conventionally called “React element.”</p>
<p><strong>Tip:</strong> A React element is a JavaScript object that defines the user interface (UI) you want to render on screen.</p>
<p>A simplified version of a React element looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myBioReactElement = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">"h1"</span>,
  <span class="hljs-attr">props</span>: {
    <span class="hljs-attr">className</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">children</span>: <span class="hljs-string">"My name is Oluwatobi."</span>,
  },
};
</code></pre>
<p><code>React.createElement()</code> is best for projects that want to avoid compiling tools like Babel. Whereas JSX is a syntactic sugar that makes React code easier to read. So, you are free to choose the syntax that works best for you (but most React projects use JSX for its simplicity).</p>
<h2 id="heading-how-to-use-jsx">How to Use JSX</h2>
<p>The following tips will help you get up and running with JSX so you can use it in your React projects.</p>
<h3 id="heading-use-jsx-like-any-javascript-expression">Use JSX like any JavaScript expression</h3>
<p>You can use JSX like any other JavaScript expression because, at <a target="_blank" href="https://codesweetly.com/web-tech-terms-e/#execution-time">execution time</a>, JSX transpiles into regular JavaScript.</p>
<p>In other words, you can store JSX expressions in variables, use them in <code>if</code> statements, or make them the return value of functions.</p>
<p><strong>Example:</strong></p>
<p><code>DisplayMyName.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> firstName = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">const</span> myFirstName = <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My first name is Oluwatobi.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
<span class="hljs-keyword">const</span> mylastName = <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My last name is Sofela.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DisplayMyName</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (firstName) {
    <span class="hljs-keyword">return</span> myFirstName;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> mylastName;
  }
}
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DisplayMyName</span> /&gt;</span></span>);
</code></pre>
<p><code>index.html</code></p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-US"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>DisplayMyName App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react@18/umd/react.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react-dom@18/umd/react-dom.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/@babel/standalone/babel.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/babel"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"DisplayMyName.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The React snippet above stores JSX code in variables. We also made it the return value of a function’s <code>if...else</code> statement.</p>
<h3 id="heading-wrap-multi-line-jsx-in-parentheses">Wrap multi-line JSX in parentheses</h3>
<p>Wrapping your JSX code in parentheses is best when it spans across multiple lines. Doing so will make your code readable and avoid the <a target="_blank" href="https://stackoverflow.com/questions/2846283/what-are-the-rules-for-javascripts-automatic-semicolon-insertion-asi">pitfalls of automatic semicolon insertion</a>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myName = (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My name is Oluwatobi.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
</code></pre>
<p>The snippet above wraps the <code>div</code> in parentheses because it spans multiple lines.</p>
<h3 id="heading-wrap-expressions-in-curly-braces">Wrap expressions in curly braces</h3>
<p>Suppose you wish to write JavaScript expressions in your JSX code. In that case, wrap the expression in curly braces like so:</p>
<p><code>ExpressionInJSX.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ExpressionInJSX</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>JSX makes it {10 * 3} times faster to build React UIs.<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>;
}
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ExpressionInJSX</span> /&gt;</span></span>);
</code></pre>
<p><code>index.html</code></p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-US"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>ExpressionInJSX App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react@18/umd/react.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react-dom@18/umd/react-dom.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/@babel/standalone/babel.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/babel"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"ExpressionInJSX.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p><strong>Tips:</strong></p>
<ul>
<li><p>React reads curly braces (<code>{...}</code>) in JSX code as a JavaScript expression.</p>
</li>
<li><p>Using curly braces to embed a JavaScript expression works only if you use it in either of two ways:</p>
<ol>
<li><p>Directly between the opening and closing JSX tags:</p>
<pre><code class="lang-xml"> <span class="hljs-tag">&lt;<span class="hljs-name">openingTag</span>&gt;</span>I have a {javaScriptExpression} content.<span class="hljs-tag">&lt;/<span class="hljs-name">closingTag</span>&gt;</span>
</code></pre>
</li>
<li><p>As the value of a JSX element’s attribute:</p>
<pre><code class="lang-xml"> <span class="hljs-tag">&lt;<span class="hljs-name">openingTag</span> <span class="hljs-attr">attribute</span>=<span class="hljs-string">{javaScriptExpression}</span>&gt;</span>I have a content<span class="hljs-tag">&lt;/<span class="hljs-name">closingTag</span>&gt;</span>
</code></pre>
</li>
</ol>
</li>
</ul>
<h3 id="heading-use-camelcase-to-name-attributes">Use camelCase to name attributes</h3>
<p>React uses <a target="_blank" href="https://codesweetly.com/naming-convention-explained/#what-is-camelcase">camelCase</a> for JSX attribute keys rather than the lowercase HTML attribute naming convention. This is because, under the hood, JSX compiles into plain JavaScript and, therefore, uses the JavaScript Web APIs.</p>
<p>In other words, instead of writing <code>readonly</code>, use <code>readOnly</code>. Likewise, instead of using <code>maxlength</code>, write <code>maxLength</code>. By doing so, React will gain access to JavaScript’s <code>readOnly</code> and <code>maxLength</code> Web APIs.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myName = (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"about-me"</span>&gt;</span>My name is Oluwatobi.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
</code></pre>
<h3 id="heading-close-empty-jsx-tags-properly">Close empty JSX tags properly</h3>
<p>React requires closing all JSX elements explicitly with <code>/&gt;</code>, including empty tags. For instance, you’ll need to write an HTML <code>&lt;img&gt;</code> element as <code>&lt;img /&gt;</code>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> emptyJSXElement = <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Click me"</span> /&gt;</span></span>;
</code></pre>
<h3 id="heading-a-react-component-can-return-only-a-single-element">A React component can return only a single element</h3>
<p>Creating two or more JSX elements from a component requires wrapping them in a single parent element. Otherwise, React will throw an error. This is because React components return only a single element.</p>
<p><strong>Example:</strong></p>
<p><code>TwoInnerUIs.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TwoInnerUIs</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My name is Oluwatobi.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Buy me a coffee<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TwoInnerUIs</span> /&gt;</span></span>);
</code></pre>
<p><code>index.html</code></p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-US"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>TwoInnerUIs App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react@18/umd/react.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react-dom@18/umd/react-dom.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/@babel/standalone/babel.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/babel"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"TwoInnerUIs.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>In the expression above, the <code>&lt;div&gt;</code> is a parent element containing two (2) inner tags.</p>
<p><strong>Tip:</strong> React allows using a <a target="_blank" href="https://react.dev/reference/react/Fragment">fragment</a> (empty tag) to group elements. Here’s an example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TwoInnerUIs</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My name is Oluwatobi.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Buy me a coffee<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TwoInnerUIs</span> /&gt;</span></span>);
</code></pre>
<p>Fragments are a great way to return multiple elements without creating unnecessary tags in the HTML DOM.</p>
<h2 id="heading-time-to-practice-with-jsx">Time to Practice with JSX 🤸‍♂️🏋️‍♀️🏊‍♀️</h2>
<p>Here is your moment to practice the JSX concepts you’ve learned.</p>
<p>In this exercise, you will convert the regular JavaScript code below to its JSX equivalent:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SupportCodeSweetly</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> React.createElement(
    <span class="hljs-string">"div"</span>,
    { <span class="hljs-attr">className</span>: <span class="hljs-string">"support-ui"</span> },
    React.createElement(
      <span class="hljs-string">"a"</span>,
      {
        <span class="hljs-attr">id</span>: <span class="hljs-string">"support-link"</span>,
        <span class="hljs-attr">className</span>: <span class="hljs-string">"support-link"</span>,
        <span class="hljs-attr">target</span>: <span class="hljs-string">"_blank"</span>,
        <span class="hljs-attr">href</span>: <span class="hljs-string">"https://www.buymeacoffee.com/codesweetly"</span>,
      },
      <span class="hljs-string">"Buy me a coffee"</span>
    ),
    <span class="hljs-string">". Thank you!"</span>
  );
}

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(React.createElement(SupportCodeSweetly));
</code></pre>
<p>Take a moment to try it yourself before looking at the solution below. Even if you have to try a couple times, go back and read the above tips, or google a few things, it’ll help you learn the concepts better.</p>
<p>Ok, now that you’ve tried…</p>
<h3 id="heading-the-solution">The solution:</h3>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SupportCodeSweetly</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"support-ui"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
        <span class="hljs-attr">id</span>=<span class="hljs-string">"support-link"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"support-link"</span>
        <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.buymeacoffee.com/codesweetly"</span>
      &gt;</span>
        Buy me a coffee
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      . Thank you!
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SupportCodeSweetly</span> /&gt;</span></span>);
</code></pre>
<p>The <code>SupportCodeSweetly</code> component returns the UI we want to display on-screen and manage with React. But what exactly is a React component?</p>
<h2 id="heading-what-is-a-react-component">What Is a React Component?</h2>
<p>A component in React is a class or function that accepts a single argument called <code>props</code> and returns an element (UI).</p>
<h3 id="heading-syntax-of-a-react-component">Syntax of a React component</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760626118056/8fb5818f-b39a-42c7-9399-1acc476604ee.webp" alt="React component syntax" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The above image illustrates the constituent parts of a React component:</p>
<ol>
<li><p>A JavaScript function with a Pascal case naming convention.</p>
</li>
<li><p>A props parameter, which is the only argument React components accept. (Tip: props is short for properties.)</p>
</li>
<li><p>The component’s body, where you place a sequence of statements like variables, hooks, and conditionals.</p>
</li>
<li><p>A return statement, which is used to output the user interface (UI) you want React to display on-screen. It can be any valid HTML element.</p>
</li>
<li><p>An invocator that executes the component to retrieve its user interface. The invocator can also pass arguments (props) to the component.</p>
</li>
</ol>
<h3 id="heading-example-of-a-react-component">Example of a React component</h3>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyBio</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>My name is {props.firstName}.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
}
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/jlj9lg?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The code in the snippet above is a function component that accepts a single argument (props) and returns a React element.</p>
<h3 id="heading-react-components-best-practices">React components best practices</h3>
<p>When you’re working with components in React, there are a few best practices you should follow:</p>
<ul>
<li><p>Capitalize the first letter of your component’s name.</p>
</li>
<li><p>Don’t use bracket notation expressions in React component tags.</p>
</li>
<li><p>React components work best as pure functions.</p>
</li>
<li><p>Create components at the top level of your file.</p>
</li>
<li><p>Split long components into smaller chunks.</p>
</li>
</ul>
<p>As it’s common practice to use components to render a list of elements, let’s now discuss how to implement this optimally.</p>
<h2 id="heading-how-to-render-lists-of-elements-from-an-array">How to Render Lists of Elements from an Array</h2>
<p>Suppose you want to create a list of React elements from an array of data. You can use the JavaScript <a target="_blank" href="https://codesweetly.com/javascript-map-method/"><code>map()</code></a> method.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;

<span class="hljs-comment">// Define the bestColors array:</span>
<span class="hljs-keyword">const</span> bestColors = [<span class="hljs-string">"Blue"</span>, <span class="hljs-string">"White"</span>, <span class="hljs-string">"Pink"</span>];

<span class="hljs-comment">// Use the bestColors array to create a list of React elements:</span>
<span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color</span>) =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{color}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>);

<span class="hljs-comment">// Render the array of &lt;li&gt; elements to the root DOM:</span>
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>);
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/dcwwqr?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above used <code>map()</code> to create a new list of React elements by converting each of <code>bestColors</code> items to <code>&lt;li&gt;</code> elements.</p>
<p>Notice that we rendered the list of elements directly in the <code>root.render()</code> method. Typically, you would use a component to do such rendering. So, let’s do some refactoring by moving the <code>bestColorsLiElements</code> variable and the <code>&lt;ul&gt;</code> element into a component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BestColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Define the bestColors array:</span>
  <span class="hljs-keyword">const</span> bestColors = [<span class="hljs-string">"Blue"</span>, <span class="hljs-string">"White"</span>, <span class="hljs-string">"Pink"</span>];
  <span class="hljs-comment">// Use the bestColors array to create a list of React elements:</span>
  <span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color</span>) =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{color}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>);
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>;
}

<span class="hljs-comment">// Render the array of &lt;li&gt; elements to the root DOM:</span>
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BestColor</span> /&gt;</span></span>);
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/pj62c3?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>Although the snippet above displays the right content on the screen, it’s not efficient. So, React throws a console error. Let’s discuss the issue.</p>
<h3 id="heading-each-react-element-in-an-array-needs-a-unique-key">Each React element in an array needs a unique key</h3>
<p>If you check your console, you will see a warning message that says: <code>Each child in a list should have a unique "key" prop.</code></p>
<p>The message means that whenever you create an array of elements, React needs you to specify a unique identity for each item in the list.</p>
<p>The unique identity keys help React identify changes to the array.</p>
<p>Let’s refactor the previous snippet so that each element in the <code>bestColorsLiElements</code> has a unique <code>key</code> prop.</p>
<h3 id="heading-how-to-add-unique-keys-to-each-react-element-in-an-array">How to add unique keys to each React element in an array</h3>
<p>There are two common ways to assign unique keys to each element of an array. The first is the unrecommended way. While the second is the best technique, it is worth noting.</p>
<h4 id="heading-not-recommended-way-to-assign-keys-to-an-array-of-react-elements">Not recommended way to assign keys to an array of React elements</h4>
<p>One way to add unique keys is to use each item’s index as its <code>key</code> prop.</p>
<p><strong>Tip:</strong> By default, if you don’t provide a <code>key</code> prop, React uses each element’s index position in the array to identify them (<code>key=0</code>, <code>key=1</code>, and so on).</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BestColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> bestColors = [<span class="hljs-string">"Blue"</span>, <span class="hljs-string">"White"</span>, <span class="hljs-string">"Pink"</span>];
  <span class="hljs-comment">// Use each item's index as its key prop:</span>
  <span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color, index</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>{color}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
  ));
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>;
}

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BestColor</span> /&gt;</span></span>);
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/yxp4sz?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above specifies a <code>key</code> prop on each <code>&lt;li&gt;</code> element. It then uses each item’s <code>index</code> as the prop’s value.</p>
<p>But note that it’s best to avoid using indexes as a React element’s <code>key</code> prop. You should use it only as a last resort when you don’t have stable IDs.</p>
<p>Whenever you use an index as the <code>key</code> prop, ensure the order of items in the array never changes. Otherwise, you may have severe issues with performance and component state.</p>
<h4 id="heading-best-way-to-assign-keys-to-an-array-of-react-elements">Best way to assign keys to an array of React elements</h4>
<p>The best way to add unique keys to each React element in an array is to use stable IDs from either of the following sources:</p>
<ul>
<li><p><strong>Database:</strong> Use the database-generated IDs as the <code>key</code> props if your data comes from a database, as they are unique by default.</p>
</li>
<li><p><code>crypto.randomUUID()</code> <strong>incrementing counter:</strong> Use the <code>randomUUID()</code> method to generate Universally Unique Identifiers if you are creating and storing your data locally. (Note: This method is a web API. So, it’s available only in supporting browsers’ HTTPS contexts.)</p>
</li>
<li><p><code>uuid</code>: An NPM package for generating Universally Unique Identifiers if you are creating and persisting your data locally. This is a good alternative to the <code>randomUUID()</code> method for cross-platform compatibility.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<p><code>index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> { bestColors } <span class="hljs-keyword">from</span> <span class="hljs-string">"./bestColors.js"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BestColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Use each item's id as its key prop:</span>
  <span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{color.id}</span>&gt;</span>{color.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
  ));
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>;
}

<span class="hljs-keyword">const</span> root = createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BestColor</span> /&gt;</span></span>);
</code></pre>
<p><code>bestColors.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> bestColors = [
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Blue"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"White"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Pink"</span> },
];
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/n56z6x?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above specifies a <code>key</code> prop on each <code>&lt;li&gt;</code> element. It then uses each item’s <code>id</code> as the prop’s value.</p>
<p><strong>Note:</strong> Each <code>key</code> prop should be unique among its siblings – not globally. It’s okay to use the same <code>key</code> for an element in a different array.</p>
<h3 id="heading-essential-things-to-know-about-assigning-keys">Essential things to know about assigning keys</h3>
<p>Here are essential facts to remember whenever you assign keys to an array of React elements.</p>
<h4 id="heading-1-set-each-array-elements-key-while-creating-the-array">1. Set each array element’s key while creating the array</h4>
<p>The right place to specify each array element’s unique key is directly inside the <code>map()</code> method <em>while creating the list of elements</em>.</p>
<p>In other words, say you extract your template element into a separate component. Set the <code>key</code> prop on the component’s invocation tag—not on the extracted template element.</p>
<p><strong>Example 1: Incorrect placement of the key prop</strong></p>
<p><code>index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> { bestColors } <span class="hljs-keyword">from</span> <span class="hljs-string">"./bestColors.js"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ColorListElement</span>(<span class="hljs-params">{ color }</span>) </span>{
  <span class="hljs-comment">// WRONG: Don't place the key outside the map() method.</span>
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{color.id}</span>&gt;</span>{color.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BestColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color</span>) =&gt;</span> (
    <span class="hljs-comment">// The key attribute above should have been set here.</span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ColorListElement</span> <span class="hljs-attr">color</span>=<span class="hljs-string">{color}</span> /&gt;</span></span>
  ));
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>;
}

<span class="hljs-keyword">const</span> root = createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BestColor</span> /&gt;</span></span>);
</code></pre>
<p><code>bestColors.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> bestColors = [
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Blue"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"White"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Pink"</span> },
];
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/frcspn?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above incorrectly sets each item’s key outside the <code>map()</code> method. You should avoid such a mistake!</p>
<p>Always set the <code>key</code> prop <em>while creating the array of elements</em>. So, the snippet above should have set the <code>key</code> on the component invocation tag – in the <code>map()</code> method.</p>
<p><strong>Example 2: Correct placement of the key prop</strong></p>
<p><code>index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> { bestColors } <span class="hljs-keyword">from</span> <span class="hljs-string">"./bestColors.js"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ColorListElement</span>(<span class="hljs-params">{ color }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{color.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BestColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color</span>) =&gt;</span> (
    <span class="hljs-comment">// CORRECT: Always define the key directly inside the map() method.</span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ColorListElement</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{color.id}</span> <span class="hljs-attr">color</span>=<span class="hljs-string">{color}</span> /&gt;</span></span>
  ));
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>;
}

<span class="hljs-keyword">const</span> root = createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BestColor</span> /&gt;</span></span>);
</code></pre>
<p><code>bestColors.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> bestColors = [
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Blue"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"White"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Pink"</span> },
];
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/n9m7w2?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above correctly sets each item’s key inside the <code>map()</code> method. This allows React to access the <code>key</code> value for each element in the array returned by the <code>map()</code> method.</p>
<p><strong>Tip:</strong> React’s reconciliation (diffing) algorithm is programmed to access the <code>key</code> of each top-level item of the array. It never looks for the <code>key</code> in the child or descendant elements.</p>
<h4 id="heading-2-react-does-not-pass-keys-to-components">2. React does not pass keys to components</h4>
<p>React neither transfers the <code>key</code> prop to components nor includes it as an attribute of a rendered element.</p>
<p>React uses keys solely to know the state of array items. They help React identify changes to the array.</p>
<p>So if you need to use a specific key’s value in your component or on your DOM element, you should explicitly pass it as the value of a different attribute.</p>
<p><strong>Example:</strong></p>
<p><code>index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> { bestColors } <span class="hljs-keyword">from</span> <span class="hljs-string">"./bestColors.js"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ColorListElement</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
      {props.color.name} (ID: {props.id})
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BestColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Use `color.id` as the `key` and `id` props' value.</span>
  <span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ColorListElement</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{color.id}</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{color.id}</span> <span class="hljs-attr">color</span>=<span class="hljs-string">{color}</span> /&gt;</span></span>
  ));
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>;
}

<span class="hljs-keyword">const</span> root = createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BestColor</span> /&gt;</span></span>);
</code></pre>
<p><code>bestColors.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> bestColors = [
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Blue"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"White"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Pink"</span> },
];
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/v7yflr?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above initializes each list item’s <code>id</code> attribute with the same value as the <code>key</code> prop. By so doing, the <code>ColorListElement</code> component can access <code>props.id</code> but not <code>props.key</code>.</p>
<h4 id="heading-3-always-generate-the-keys-outside-your-components">3. Always generate the keys outside your components</h4>
<p>Never generate keys on the fly (while <a target="_blank" href="https://codesweetly.com/web-tech-terms-r/#react-render">rendering</a> your components). Instead, create them in your data outside your components. Otherwise, React will recreate the elements on every rendering cycle because the <code>key</code>’s value will always be different.</p>
<p><strong>Example 1: Incorrect place to generate the key prop</strong></p>
<p><code>index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> { bestColors } <span class="hljs-keyword">from</span> <span class="hljs-string">"./bestColors.js"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BestColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// WRONG: Never generate keys on the fly.</span>
  <span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{crypto.randomUUID()}</span>&gt;</span>{color}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
  ));
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>;
}

<span class="hljs-keyword">const</span> root = createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BestColor</span> /&gt;</span></span>);
</code></pre>
<p><code>bestColors.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// The keys' values should have been set here (outside the component while creating your data).</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> bestColors = [<span class="hljs-string">"Blue"</span>, <span class="hljs-string">"White"</span>, <span class="hljs-string">"Pink"</span>];
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/lhwknv?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above incorrectly generated each element’s key while rendering the <code>BestColor</code> component. You should avoid such a mistake to prevent subtle bugs caused by recreating the elements on every render.</p>
<p>Always create each <code>key</code>’s value in your data outside the component.</p>
<p><strong>Example 2: Correct place to generate the key prop</strong></p>
<p><code>index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> { bestColors } <span class="hljs-keyword">from</span> <span class="hljs-string">"./bestColors.js"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BestColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> bestColorsLiElements = bestColors.map(<span class="hljs-function">(<span class="hljs-params">color</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{color.id}</span>&gt;</span>{color.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
  ));
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>{bestColorsLiElements}<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>;
}

<span class="hljs-keyword">const</span> root = createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BestColor</span> /&gt;</span></span>);
</code></pre>
<p><code>bestColors.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// CORRECT: Always generate the key in your data outside the component.</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> bestColors = [
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Blue"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"White"</span> },
  { <span class="hljs-attr">id</span>: crypto.randomUUID(), <span class="hljs-attr">name</span>: <span class="hljs-string">"Pink"</span> },
];
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/n56z6x?file=%2Fsrc%2Findex.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above correctly generated each element’s key in the array data outside the component.</p>
<h2 id="heading-how-to-handle-events-in-react">How to Handle Events in React</h2>
<p>Event handling in React involves configuring your JSX elements to respond to user interactions on them (such as mouse clicks, form submission, and element focus).</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">jsxTag</span> <span class="hljs-attr">onEvent</span>=<span class="hljs-string">{handleEvent}</span>&gt;</span>UI Content<span class="hljs-tag">&lt;/<span class="hljs-name">jsxTag</span>&gt;</span>
</code></pre>
<p>Here’s what’s going on:</p>
<ul>
<li><p><code>jsxTag</code>: React elements like <code>&lt;div&gt;</code>, <code>&lt;button&gt;</code>, and <code>&lt;input&gt;</code>.</p>
</li>
<li><p><code>onEvent</code>: The event listener you want to add to the React element. Some examples are <code>onClick</code>, <code>onBlur</code>, and <code>onHover</code>.</p>
</li>
<li><p><code>handleEvent</code>: The event handler function you want to use to handle (respond to) the specified <code>onEvent</code> type.</p>
</li>
</ul>
<p><strong>Tip:</strong> Although you can name the event handler anything you prefer, the typical naming convention is to prefix the event’s name with “handle”. For instance, if the event’s name is <code>focus</code>, the handler’s name will be <code>handleFocus</code>.</p>
<h3 id="heading-types-of-event-handlers">Types of event handlers</h3>
<p>There are two typical ways to define the event handler function in React:</p>
<ul>
<li><p><strong>Inline event handler:</strong> A function defined directly on a JSX element’s opening tag as the value of the event listener prop (<code>onEvent</code>).</p>
</li>
<li><p><strong>Referenced event handler:</strong> A function defined as a separate (independent) logic and linked to an event listener attribute (<code>onEvent</code>) by name referencing.</p>
</li>
</ul>
<h4 id="heading-example-inline-event-handler">Example: Inline event handler</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> alert("You clicked the heading!")}&gt;
      Oluwatobi is my name.
    <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
  );
}
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/7tx7l5?file=%2Fsrc%2Fcomponents%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<h4 id="heading-example-referenced-event-handler">Example: Referenced event handler</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>Oluwatobi is my name.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>;
}

<span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> alert(<span class="hljs-string">"You clicked the heading!"</span>);
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/msfszz?file=%2Fsrc%2Fcomponents%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>React components have a unique memory that allows them to remember things between renderings. This memory is called “state.”</p>
<h2 id="heading-what-is-react-state">What Is React State?</h2>
<p>React state is a <em>component’s memory</em> for storing data that React should remember during a component’s re-rendering and whose update should trigger a new render.</p>
<h3 id="heading-syntax-of-react-state">Syntax of React state:</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [state, setState] = useState(initialState);

  <span class="hljs-comment">// ...</span>
}
</code></pre>
<ul>
<li><p><code>state</code>: The variable containing the component’s state value.</p>
</li>
<li><p><code>setState</code>: A function for updating the state value.</p>
</li>
<li><p><code>useState</code>: The state Hook for initializing and retrieving the component’s state.</p>
</li>
</ul>
<h3 id="heading-example-of-react-state">Example of React state:</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AboutCompany</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [age, setAge] = useState(<span class="hljs-number">5</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateAge</span>(<span class="hljs-params"></span>) </span>{
    setAge(age + <span class="hljs-number">1</span>);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>CodeSweetly is {age} years old!<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{updateAge}</span>&gt;</span>
        Click to update age
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AboutCompany;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/9mlsl7?file=%2Fsrc%2FAboutCompany.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>When a user clicks the button UI, the <code>onClick</code> event triggers the <code>updateAge</code> event handler, which uses the <code>setAge</code> setter function to update the component’s <code>age</code> state.</p>
<p><strong>Tip:</strong> React will trigger a re-render of your component every time you use <code>useState</code>’s setter function to update your state. But what exactly do the terms “trigger” and “render” mean?</p>
<h3 id="heading-react-trigger-vs-render-vs-commit-vs-paint">React Trigger vs Render vs Commit vs Paint</h3>
<p>Triggering, rendering, committing, and painting are the steps involved in displaying React UIs on screen. Here are the differences between the four steps:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760637870319/ed8ae7a7-67c1-468a-ba5f-dbbafed8deb0.webp" alt="React Component's Lifecyle" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The above slide illustrates the four phases in the lifecycle of a component’s UI:</p>
<ul>
<li><p><strong>Trigger:</strong> Specifies the component whose UI you want to display on the screen.</p>
</li>
<li><p><strong>Render:</strong> Calls the component you’ve triggered.</p>
</li>
<li><p><strong>Commit:</strong> Updates the DOM with the UI of the rendered component.</p>
</li>
<li><p><strong>Paint:</strong> Converts the DOM code you’ve committed into user-friendly elements that users can interact with in their browsers.</p>
</li>
</ul>
<p>Let’s discuss these differences in detail.</p>
<h3 id="heading-what-does-it-mean-to-trigger-a-render-in-react">What does it mean to trigger a render in React?</h3>
<p>The trigger event is the first step in displaying a React user interface (UI) on screen. It specifies the component whose UI you want to display on the screen. This event happens on two occasions:</p>
<ol>
<li>When the app starts running. The React application uses the <code>createRoot</code> method to specify the component whose UI you want to render to a DOM node.</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> DonationUI <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/DonationUI.js"</span>;

<span class="hljs-comment">// When the app starts running, you need to use createRoot and its render method to trigger an initial rendering of the app's root component.</span>
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DonationUI</span> /&gt;</span></span>);
</code></pre>
<p>The snippet above does the following:</p>
<ul>
<li><p>Uses the <code>ReactDOM.createRoot()</code> method to create a <code>ReactDOMRoot</code> object instance for the <code>root</code> element argument.</p>
</li>
<li><p>Use the object instance’s <code>render()</code> method to trigger an initial rendering of the <code>DonationUI</code> component.</p>
</li>
</ul>
<p>In other words, the <code>createRoot().render()</code> method specifies <code>DonationUI</code> as the component whose UI React should display in the <code>root</code> HTML element.</p>
<ol start="2">
<li>The second reason a trigger event can happen is when a component’s (or its ancestors’) state gets updated with a set function.</li>
</ol>
<p><code>DonationUI.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DonationUI</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [donate, setDonate] = React.useState(<span class="hljs-literal">false</span>);
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUserInterface</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (donate) {
      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.buymeacoffee.com/codesweetly"</span>&gt;</span>Support page<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>.
          Thank you so much!
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
      );
    }
    <span class="hljs-comment">// The setDonate function will trigger a re-rendering of the DonationUI component.</span>
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setDonate(true)}&gt;Buy me a coffee<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
  }
  <span class="hljs-keyword">return</span> createUserInterface();
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DonationUI;
</code></pre>
<p>The snippet above does the following:</p>
<ol>
<li><p>Defines a component named <code>DonationUI</code>.</p>
</li>
<li><p>Initializes the component’s state with the Boolean value <code>false</code>.</p>
</li>
<li><p>Programs the component to return a paragraph element if the state’s <code>donate</code> variable is <code>true</code>. Otherwise, it should return a button element.</p>
</li>
</ol>
<p>When users click the button element, the <code>setDonate</code> setter function will trigger a re-rendering of the <code>DonationUI</code> component. Below are the entry script and the HTML code so you can try it yourself locally.</p>
<p><code>index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> DonationUI <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/DonationUI"</span>;

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DonationUI</span> /&gt;</span></span>);
</code></pre>
<p><code>index.html</code></p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-US"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>CodeSweetly DonationUI<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"index.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/95nvmr?file=%2Fsrc%2Fcomponents%2FDonationUI.js"><strong>Try it on CodeSandbox</strong></a></p>
<h3 id="heading-what-does-it-mean-to-render-react-components">What does it mean to render React components?</h3>
<p>The rendering step is when React <a target="_blank" href="https://codesweetly.com/invoke-vs-call/">invokes (calls)</a> the component you’ve triggered with either the <code>createRoot</code> method or a set function. Rendering causes React to invoke a component to produce the UI you want to display on the screen. The component React will render depends on the moment the trigger event occurred:</p>
<ul>
<li><p><strong>For an initial trigger (at the start of the app),</strong> React will invoke the app’s root component.</p>
</li>
<li><p><strong>For update triggers (whenever a component’s state gets updated),</strong> React will call the function component whose state update initiated the trigger event.</p>
</li>
</ul>
<p><strong>Tip:</strong> Rendering a component means “calling a component” to retrieve its user interface (UI).</p>
<h3 id="heading-what-does-it-mean-to-commit-a-react-ui-to-the-browsers-dom">What does it mean to commit a React UI to the browser’s DOM?</h3>
<p>The committing stage is when React updates the DOM with the UI of the rendered component.</p>
<p>There are some important things to note about this process:</p>
<ul>
<li><p><strong>For an initial render (at the start of the app),</strong> React will initialize the root DOM with the root component’s UI. It will use the <code>appendChild()</code> JavaScript API to append the DOM nodes (UI) retrieved from the component into the app’s root HTML element.</p>
</li>
<li><p><strong>For subsequent re-rendering (after the initial commit),</strong> React will only update the DOM nodes if there’s a difference between the previous rendering output and the latest one. No changes will occur if the component’s latest output is the same as the previously committed one.</p>
</li>
</ul>
<h3 id="heading-what-does-it-mean-to-paint-the-dom-nodes-on-the-screen">What does it mean to paint the DOM nodes on the screen?</h3>
<p>The painting (browser rendering) stage is when the browser repaints the screen to convert the DOM code to user-friendly elements. This is a browser-level process that begins once React has finished updating (committing) the DOM nodes.</p>
<p>Sometimes, components need to store information that shouldn’t trigger a render when updated. In these situations, you can use a ref.</p>
<h2 id="heading-what-is-the-react-ref-hook">What Is the React Ref Hook?</h2>
<p>The React Ref Hook lets you store values that don’t trigger re-renders when changed.</p>
<h3 id="heading-syntax-of-the-react-ref-hook">Syntax of the React ref Hook</h3>
<p>The <code>useRef</code> Hook accepts only one optional argument. Here is the syntax:</p>
<pre><code class="lang-javascript">useRef(initialValue);
</code></pre>
<ul>
<li><p><code>initialValue</code>: The value to store in the component’s ref memory. Any JavaScript data type is allowed.</p>
</li>
<li><p><code>useRef()</code>: Returns an object (<code>{ current: initialValue }</code>).</p>
</li>
</ul>
<h3 id="heading-example-of-the-react-ref-hook">Example of the React ref Hook:</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> myNameRef = useRef(<span class="hljs-string">"Oluwatobi"</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleClick</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(myNameRef.current); <span class="hljs-comment">// Outputs: "Oluwatobi"</span>
  }

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/mgsxyq?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above used the <code>useRef</code> Hook to store a value (<code>"Oluwatobi"</code>) whose update shouldn’t trigger re-renders.</p>
<h3 id="heading-react-ref-hook-best-practices">React ref Hook best practices</h3>
<p>When you’re working with React’s ref hook, there are some best practices you should follow:</p>
<ul>
<li><p>Use dot syntax to access and update a ref object’s value instead of square bracket notation.</p>
</li>
<li><p>Avoid accessing or updating the <code>current</code> property during rendering to maintain the purity of your components.</p>
</li>
<li><p>Don’t use a function instance as your <code>initialValue</code>. Pass the function itself, not its output.</p>
</li>
<li><p>You can use the React ref Hook to manage your HTML DOM nodes.</p>
</li>
</ul>
<p>But what’s the difference between refs, states, and variables, I hear you ask? Let’s find out below.</p>
<h2 id="heading-variables-vs-refs-vs-states-in-react">Variables vs Refs vs States in React</h2>
<p>In React, variables, refs, and states allow you to store and mutate data. But they work in different ways. Here are the main distinctions between them:</p>
<ol>
<li><p>Does its value persist during re-rendering?</p>
<ul>
<li><p>React Ref: Yes</p>
</li>
<li><p>React State: Yes</p>
</li>
<li><p>JavaScript Variable: No</p>
</li>
</ul>
</li>
<li><p>Would updating its value trigger a re-rendering of the component?</p>
<ul>
<li><p>React Ref: No</p>
</li>
<li><p>React State: Yes</p>
</li>
<li><p>JavaScript Variable: No</p>
</li>
</ul>
</li>
<li><p>Is it plain JavaScript?</p>
<ul>
<li><p>React Ref: Yes</p>
</li>
<li><p>React State: No</p>
</li>
<li><p>JavaScript Variable: Yes</p>
</li>
</ul>
</li>
<li><p>Can you declare it outside a component?</p>
<ul>
<li><p>React Ref: No</p>
</li>
<li><p>React State: No</p>
</li>
<li><p>JavaScript Variable: Yes</p>
</li>
</ul>
</li>
<li><p>Is it usable in conditional statements, loops, or nested functions?</p>
<ul>
<li><p>React Ref: No</p>
</li>
<li><p>React State: No</p>
</li>
<li><p>JavaScript Variable: Yes</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-how-do-variables-work-in-react">How do variables work in React?</h3>
<p>A <a target="_blank" href="https://codesweetly.com/javascript-variable/">variable</a>’s value does not persist during re-rendering. Its value resets at the beginning of a new rendering.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> myVar = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">const</span> [myState, setMyState] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateVar</span>(<span class="hljs-params"></span>) </span>{
    myVar = myVar + <span class="hljs-number">1</span>;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"myVar ="</span>, myVar);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateState</span>(<span class="hljs-params"></span>) </span>{
    setMyState(myState + <span class="hljs-number">1</span>);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Variable: {myVar}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>State: {myState}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{updateVar}</span>&gt;</span>Update Variable<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{updateState}</span>&gt;</span>Update State<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesweetly.com/variables-vs-refs-vs-states-in-react/try-it-sdk-vitejs-vite-u6yjihmv"><strong>Try Editing It</strong></a></p>
<p>The snippet above will:</p>
<ul>
<li><p>Increment the variable’s value when you click the “Update Variable” button. This modification doesn’t trigger a re-rendering of the component because React doesn’t track a variable’s changes.</p>
</li>
<li><p>Increment the state’s value when you click the “Update State” button. This modification triggers a re-rendering of the component because React requests a re-render whenever you modify the state.</p>
</li>
<li><p>Reset the variable’s value to zero (0) during each re-rendering of the App component. Therefore, the rendered variable’s value will always be zero (0).</p>
</li>
</ul>
<h3 id="heading-how-do-refs-work-in-react">How do refs work in React?</h3>
<p>A ref’s value persists during re-rendering, but modifying it doesn’t cause React to re-render the component. In other words, a ref is a plain <a target="_blank" href="https://codesweetly.com/javascript-properties-object/">JavaScript object</a> whose value React remembers while re-rendering your component. But React doesn’t track changes to the ref’s value. So, its modifications don’t trigger a new rendering.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> myRef = useRef(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> [myState, setMyState] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateRef</span>(<span class="hljs-params"></span>) </span>{
    myRef.current = myRef.current + <span class="hljs-number">1</span>;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"myRef ="</span>, myRef);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateState</span>(<span class="hljs-params"></span>) </span>{
    setMyState(myState + <span class="hljs-number">1</span>);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Ref: {myRef.current}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>State: {myState}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{updateRef}</span>&gt;</span>Update Ref<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{updateState}</span>&gt;</span>Update State<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesweetly.com/variables-vs-refs-vs-states-in-react/try-it-sdk-vitejs-vite-xyjh2fev"><strong>Try Editing It</strong></a></p>
<p>The snippet above will:</p>
<ul>
<li><p>Increment the ref’s value when you click the “Update Ref” button. This modification doesn’t trigger a re-rendering of the component because React doesn’t monitor the ref’s changes.</p>
</li>
<li><p>Increment the state’s value when you click the “Update State” button. This modification triggers a re-rendering of the component because React requests a re-render whenever you modify the state.</p>
</li>
<li><p>Retains the ref and state’s value during each re-rendering of the App component.</p>
</li>
</ul>
<h3 id="heading-how-do-states-work-in-react">How do states work in React?</h3>
<p>A state’s value persists during re-rendering. Modifying it also causes React to re-render the component.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> myVar = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">const</span> myRef = useRef(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> [myState, setMyState] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateVarAndRef</span>(<span class="hljs-params"></span>) </span>{
    myVar = myVar + <span class="hljs-number">1</span>;
    myRef.current = myRef.current + <span class="hljs-number">1</span>;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"myVar ="</span>, myVar);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"myRef ="</span>, myRef);
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateState</span>(<span class="hljs-params"></span>) </span>{
    setMyState(myState + <span class="hljs-number">1</span>);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Variable: {myVar}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Ref: {myRef.current}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>State: {myState}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{updateVarAndRef}</span>&gt;</span>Update Variable and Ref<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{updateState}</span>&gt;</span>Update State<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesweetly.com/variables-vs-refs-vs-states-in-react/try-it-sdk-vitejs-vite-gklkzfps"><strong>Try Editing It</strong></a></p>
<p>The snippet above will:</p>
<ul>
<li><p>Increment the variable and ref’s value when you click the “Update Variable and Ref” button. This modification doesn’t trigger a re-rendering of the component because React doesn’t monitor changes to the variable or ref.</p>
</li>
<li><p>Increment the state’s value when you click the “Update State” button. This modification triggers a re-rendering of the component because React requests a re-render whenever you modify the state.</p>
</li>
<li><p>Resets the variable’s value during each re-rendering of the App component, while retaining the ref and state’s data.</p>
</li>
</ul>
<h3 id="heading-tips-on-using-variables-refs-and-states-in-react">Tips on using variables, refs, and states in React</h3>
<ul>
<li><p>Use variables for values that should reset on every rendering of the component.</p>
</li>
<li><p>Use the Ref Hook to store values that users do not need to see on screen, as changes to the ref will not trigger a re-rendering of the component.</p>
</li>
<li><p>React state is ideal for storing values that you want to display on the screen, as state changes trigger a re-rendering of the component.</p>
</li>
</ul>
<p>React components sometimes need to fetch data or change the DOM during different lifecycle phases: trigger, render, commit, and paint. The Effect Hook can help with these tasks.</p>
<h2 id="heading-what-is-the-useeffect-hook">What Is the useEffect Hook?</h2>
<p>The <code>useEffect</code> hook lets function components perform side effects outside React.</p>
<h3 id="heading-syntax-of-the-useeffect-hook">Syntax of the useEffect Hook</h3>
<p>The <code>useEffect</code> hook accepts two arguments. Here’s the syntax:</p>
<pre><code class="lang-javascript">useEffect(callback, array);
</code></pre>
<ul>
<li><p><code>callback</code>: The required setup function for the useEffect hook.</p>
</li>
<li><p><code>array</code>: (Optional) The reactive dependencies list that indicates when React runs the callback.</p>
</li>
</ul>
<p><strong>Tip:</strong> React runs the setup function after the component mounts or when dependencies change.</p>
<h3 id="heading-example-of-the-useeffect-hook">Example of the useEffect Hook:</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AboutCompany</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [age, setAge] = useState(<span class="hljs-number">5</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">document</span>.title = <span class="hljs-string">`🥳🎁🎉 It's CodeSweetly's birthday! 🎉🎁🥳`</span>;
  });

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>CodeSweetly is {age} years old!<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setAge(age + 1)}&gt;
        Click to update age
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AboutCompany;
</code></pre>
<p>The <code>useEffect</code> code updates the browser’s title after the UI finishes rendering.</p>
<h3 id="heading-useeffect-hooks-best-practices">useEffect Hook’s best practices</h3>
<p>As always, there are some best practices to use this hook most effectively:</p>
<ul>
<li><p>Use <code>useEffect</code> to connect with things outside your React app, such as APIs or timers. If your code has no side effects, you likely don’t need it.</p>
</li>
<li><p>Avoid adding values to the dependency array unless your effect uses them. Include only the state and props needed to prevent unnecessary re-runs.</p>
</li>
<li><p>Declare static objects and functions outside components. Place dynamic ones inside your Effect Hook.</p>
</li>
<li><p>When depending on object props, list each primitive value used in your effect instead of the entire object.</p>
</li>
<li><p>Use <code>StrictMode</code> to help catch common useEffect hook issues during development.</p>
</li>
</ul>
<p>With the basics of React covered, let’s discuss styling.</p>
<h2 id="heading-how-to-style-react-components">How to Style React Components</h2>
<p>The four primary ways to style React elements are:</p>
<ul>
<li><p>CSS style sheets</p>
</li>
<li><p>Inline style attributes</p>
</li>
<li><p>CSS Modules</p>
</li>
<li><p>CSS-in-JS Libraries</p>
</li>
</ul>
<p>Let’s discuss the four styling techniques.</p>
<h3 id="heading-how-to-use-css-style-sheets-to-style-react-elements">How to use CSS style sheets to style React elements</h3>
<p>Below are the steps to style JSX elements with regular CSS style sheets.</p>
<h4 id="heading-1-create-a-css-stylesheet">1. Create a CSS stylesheet</h4>
<p>First, create a CSS stylesheet in your React projects.</p>
<pre><code class="lang-console">touch styles.css
</code></pre>
<p><strong>Tip:</strong> You can create the stylesheet anywhere in your project directory.</p>
<h4 id="heading-2-define-your-ruleset">2. Define your ruleset</h4>
<p>Open the newly created CSS file and declare your styles.</p>
<p><strong>Example:</strong></p>
<p><code>styles.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.text</span> {
  <span class="hljs-attribute">color</span>: seagreen;
  <span class="hljs-attribute">font-weight</span>: bold;
}
</code></pre>
<p>The CSS snippet above instructs browsers to apply a <code>seagreen</code> color and <code>bold</code> font weight on elements with a <code>text</code> class name.</p>
<h4 id="heading-3-apply-the-stylesheets-ruleset-to-your-element">3. Apply the stylesheet’s ruleset to your element</h4>
<p>Import your stylesheet into the component file containing the element you wish to style. Then, apply the stylesheet’s ruleset to it.</p>
<p><strong>Example:</strong></p>
<p><code>App.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Import your stylesheet (the path to your stylesheet may be different).</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"../styles.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text"</span>&gt;</span>Oluwatobi is my name.<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/mq5xzp?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above instructs React to apply the <code>"text"</code> ruleset on the element with a <code>className="text"</code> attribute.</p>
<h3 id="heading-how-to-use-the-inline-style-attribute-to-style-react-elements">How to use the inline <code>style</code> attribute to style React elements</h3>
<p>React allows you to apply inline styles to JSX elements in the same way as inline CSS works in HTML. But there are some differences to keep in mind.</p>
<p>First, HTML applies inline styles as a string value:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color:seagreen; font-weight:bold;"</span>&gt;</span>Oluwatobi is my name.<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>But in React, you must define inline styles as objects, not strings:</p>
<pre><code class="lang-javascript">&lt;div style={{ <span class="hljs-attr">color</span>: <span class="hljs-string">"seagreen"</span>, <span class="hljs-attr">fontWeight</span>: <span class="hljs-string">"bold"</span> }}&gt;
  Oluwatobi is my name.
&lt;/div&gt;
</code></pre>
<p>The snippet above uses two sets of curly braces because in JSX (as I mentioned above), you wrap <a target="_blank" href="https://codesweetly.com/javascript-statement/#what-is-a-javascript-expression-statement">JavaScript expressions</a> inside curly braces: for instance, <code>&lt;div&gt;{myNameVariable}&lt;/div&gt;</code>.</p>
<p>So, suppose the expression is a JavaScript object literal. In that case, you will need two sets of curly braces: for instance, <code>&lt;div&gt;{{ name: "Oluwatobi" }}&lt;/div&gt;</code>.</p>
<p>Therefore, in <code>style={{ color: seagreen, fontWeight: bold }}</code>, the first set of curly braces (<code>{...}</code>) tells React that you want to write a JavaScript expression. The second set of curly braces (<code>{ color: seagreen, fontWeight: bold }</code>) is the JavaScript expression (an object) you are assigning as the <code>style</code> attribute’s value.</p>
<p><strong>Example:</strong></p>
<p><code>App.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> "<span class="hljs-attr">seagreen</span>", <span class="hljs-attr">fontWeight:</span> "<span class="hljs-attr">bold</span>" }}&gt;</span>
      Oluwatobi is my name.
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/84cmjf?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The React snippet above instructs the computer to apply an inline style to the <code>div</code> element.</p>
<p>You can see that we wrote <code>fontWeight</code> in <a target="_blank" href="https://codesweetly.com/naming-convention-explained/#what-is-camelcase">camelCase</a>. This is because, under the hood, JSX compiles into plain JavaScript. So it uses the JavaScript Web APIs attribute naming convention.</p>
<p>To make your code easier to read, consider storing your inline style object in a separate variable like so:</p>
<p><code>App.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Store your inline style object in a variable:</span>
  <span class="hljs-keyword">const</span> textStyles = { <span class="hljs-attr">color</span>: <span class="hljs-string">"seagreen"</span>, <span class="hljs-attr">fontWeight</span>: <span class="hljs-string">"bold"</span> };
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{textStyles}</span>&gt;</span>Oluwatobi is my name.<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/2llmwy?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p><strong>Tip:</strong> The Tailwind CSS framework is an inline styling tool that provides utility classes you can apply directly to an element. It offers additional features that are often lacking in regular inline styling. For example, Tailwind allows you to configure media queries and event states (such as <code>hover</code>, <code>focus</code>, and <code>active</code>) in inline styles.</p>
<h3 id="heading-how-to-use-css-modules-to-style-react-elements">How to use CSS modules to style React elements</h3>
<p>As defined on the official <a target="_blank" href="https://github.com/css-modules/css-modules">documentation</a>, a CSS Module is a CSS file in which all class names and animation names are scoped locally by default.</p>
<p>CSS Modules share many similarities with a regular CSS style sheet. But there are some essential differences.</p>
<h4 id="heading-1-filename-convention">1. Filename convention</h4>
<p>The syntax for naming a regular CSS stylesheet is <code>[name].css</code>: for instance, <code>codesweetly-styles.css</code>.</p>
<p>But a CSS module’s file naming convention is <code>[name].module.css</code>: for instance, <code>codesweetly-styles.module.css</code>.</p>
<h4 id="heading-2-styles-scope">2. Styles scope</h4>
<p>Importing a CSS style sheet into your script file makes its rulesets available <em>globally</em> to all components (and child components) of that script.</p>
<p>But importing a CSS module into your script file only makes its rulesets available <em>locally</em> to the component that invokes the module’s rule. Also, that component must be in the script that imports the CSS module.</p>
<p><strong>Example:</strong></p>
<p>Create a regular CSS stylesheet in your React project and add some rules to it:</p>
<p><code>styles.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.imageInfo</span> {
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#442109</span>;
}
</code></pre>
<p>Also, create a CSS module in the same project and add some rules to it:</p>
<p><code>styles.module.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.imageInfo</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">8px</span> ridge <span class="hljs-number">#71380f</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#ffe5b4</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span> <span class="hljs-number">0</span> <span class="hljs-number">7px</span>;
}
</code></pre>
<p>Import both the CSS stylesheet and CSS module you’ve just created into your script file:</p>
<p><code>App.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">"../styles.css"</span>;
<span class="hljs-keyword">import</span> codesweetlyStyles <span class="hljs-keyword">from</span> <span class="hljs-string">"../styles.module.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"imageInfo"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Random Image<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://picsum.photos/400/400"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Random Image"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Get a new image each time you refresh your browser.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/3t3nwt?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>Go ahead and run your app and check its output in your browser.</p>
<p>After running your app, you will notice that React only applied the CSS stylesheet’s ruleset, not the CSS module’s own.</p>
<p>React did so because the stylesheet’s ruleset is globally available to all elements (and child components) of the page where you imported the sheet.</p>
<p>But the ruleset in the module is locally available only to the component that explicitly invokes the rule.</p>
<p>So, to use your CSS module’s style in your component, you must explicitly execute it like so:</p>
<p><code>App.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">"../styles.css"</span>;
<span class="hljs-keyword">import</span> codesweetlyStyles <span class="hljs-keyword">from</span> <span class="hljs-string">"../styles.module.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">imageInfo</span> ${<span class="hljs-attr">codesweetlyStyles.imageInfo</span>}`}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Random Image<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://picsum.photos/400/400"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Random Image"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Get a new image each time you refresh your browser.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/45lkpf?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above uses the <code>codesweetlyStyles.imageInfo</code> code to instruct React to apply the CSS module’s <code>imageInfo</code> ruleset to the <code>div</code> element.</p>
<h4 id="heading-3-composition">3. Composition</h4>
<p>To compose styles together while using a regular CSS style sheet, you must apply multiple classes to your element.</p>
<p><strong>Example: Compose rulesets with regular CSS style sheets</strong></p>
<p><code>styles.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">4px</span> solid blueviolet;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span> <span class="hljs-number">15px</span>;
}

<span class="hljs-selector-class">.text</span> {
  <span class="hljs-attribute">color</span>: seagreen;
  <span class="hljs-attribute">font-weight</span>: bold;
}
</code></pre>
<p><code>App.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">"../styles.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container text"</span>&gt;</span>Oluwatobi is my name.<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/w6h74d?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>Using multiple classes on an element to implement style composition is not the best practice because CSS will use the order of style definitions in the stylesheet to determine the order of precedence based on the CSS cascading rules.</p>
<p>But CSS modules provide a <code>composes</code> declaration that offers greater flexibility in composing your styles to suit your project’s needs.</p>
<p><strong>Example: Compose rulesets with CSS modules</strong></p>
<p><code>styles.module.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">4px</span> solid blueviolet;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span> <span class="hljs-number">15px</span>;
}

<span class="hljs-selector-class">.text</span> {
  <span class="hljs-attribute">composes</span>: container;
  <span class="hljs-attribute">color</span>: seagreen;
  <span class="hljs-attribute">font-weight</span>: bold;
}
</code></pre>
<p><code>App.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"../styles.module.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.text}</span>&gt;</span>Oluwatobi is my name.<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/j6yl9z?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>Although you can define multiple <code>composes</code> declarations in a ruleset, they must precede other rules.</p>
<p><strong>Example: All</strong> <code>composes</code> <strong>declarations must come before other rules</strong></p>
<p><code>styles.module.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">4px</span> solid blueviolet;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span> <span class="hljs-number">15px</span>;
}

<span class="hljs-selector-class">.curved</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.text</span> {
  <span class="hljs-attribute">composes</span>: container;
  <span class="hljs-attribute">composes</span>: curved;
  <span class="hljs-attribute">color</span>: seagreen;
  <span class="hljs-attribute">font-weight</span>: bold;
}
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/3lqshk?file=%2Fsrc%2Fstyles.module.css"><strong>Try it on CodeSandbox</strong></a></p>
<p>You can simplify the <code>.text</code> ruleset by using a single <code>composes</code> declaration for multiple classes.</p>
<p><strong>Example: Compose classes with a single</strong> <code>composes</code> <strong>declaration</strong></p>
<p><code>styles.module.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">4px</span> solid blueviolet;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span> <span class="hljs-number">15px</span>;
}

<span class="hljs-selector-class">.curved</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.text</span> {
  <span class="hljs-attribute">composes</span>: container curved;
  <span class="hljs-attribute">color</span>: seagreen;
  <span class="hljs-attribute">font-weight</span>: bold;
}
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/x4zfyn?file=%2Fsrc%2Fstyles.module.css"><strong>Try it on CodeSandbox</strong></a></p>
<h3 id="heading-how-to-use-a-css-in-js-library-to-style-react-elements">How to use a CSS-in-JS library to style React elements</h3>
<p>A CSS-in-JS library allows you to use the complete features of CSS directly within your JavaScript file.</p>
<p>Some of the popular CSS-in-JS libraries are Linaria, Emotion, Pigment CSS, and Panda CSS.</p>
<p>Feel free to try any CSS-in-JS library you prefer. Here, we’ll use Emotion to illustrate how such a styling technique works in a React application.</p>
<p>So, go ahead and install the library into any of your React projects by running:</p>
<pre><code class="lang-console">npm i @emotion/react@11.14.0
</code></pre>
<p>After you’ve installed Emotion, import it and use it in your component file like so:</p>
<p><code>App.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// The comment below is essential. Emotion will not work without it.</span>
<span class="hljs-comment">/** <span class="hljs-doctag">@jsxImportSource </span><span class="hljs-doctag">@emotion</span>/react */</span>

<span class="hljs-comment">// Define your styles using the JavaScript object syntax.</span>
<span class="hljs-keyword">const</span> codesweetlyStyles = {
  <span class="hljs-attr">border</span>: <span class="hljs-string">"8px ridge #71380f"</span>,
  <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#ffe5b4"</span>,
  <span class="hljs-attr">padding</span>: <span class="hljs-string">"20px 0 7px"</span>,
  <span class="hljs-attr">textAlign</span>: <span class="hljs-string">"center"</span>,
  <span class="hljs-attr">color</span>: <span class="hljs-string">"maroon"</span>,
  <span class="hljs-string">"@media(min-width: 768px)"</span>: {
    <span class="hljs-attr">color</span>: <span class="hljs-string">"darkslategray"</span>,
  },
};

<span class="hljs-comment">// Apply the styles to your element.</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">css</span>=<span class="hljs-string">{codesweetlyStyles}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Random Image<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://picsum.photos/400/400"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Random Image"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Get a new image each time you refresh your browser.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><a target="_blank" href="https://codesandbox.io/p/sandbox/t4ttkx?file=%2Fsrc%2FApp.js"><strong>Try it on CodeSandbox</strong></a></p>
<p>The snippet above does the following:</p>
<ol>
<li><p>Uses the <code>/** @jsxImportSource @emotion/react */</code> comment (JSX Pragma) to tell the Babel JSX plugin to convert the script’s JSX calls to an Emotion function called <code>jsx</code> instead of <code>React.createElement</code>. Make sure you place the pragma directive above your import statements. Otherwise, the Emotion library will not work.</p>
</li>
<li><p>Defines styles in a JavaScript object.</p>
</li>
<li><p>Uses Emotion’s <code>css</code> prop feature to apply the styles to the JSX element.</p>
</li>
</ol>
<p>Notice that the <code>css</code> prop is like the inline <code>style</code> attribute. The main difference is that the <code>css</code> props support more CSS features like nested selectors, auto vendor-prefixing, media queries, and event states (such as <code>hover</code>, <code>focus</code>, and <code>active</code>). So, using CSS-in-JS libraries like Emotion lets you write highly flexible and responsive styles directly in your JavaScript files.</p>
<p><strong>Tip:</strong> The <code>css</code> prop works on any element that supports the <code>className</code> attribute.</p>
<p>Now, go ahead and run your app and check its output in your browser.</p>
<p>And that’s it! You now know how to use the CSS-in-JS library to style your React elements.</p>
<p>I used Emotion in this article because I like how clean its syntax looks. Feel free to test other CSS-in-JS libraries, such as Pigment CSS. You may find one that suits you better.</p>
<h2 id="heading-overview">Overview</h2>
<p>In this handbook, we discussed the core concepts you need to know to start building applications with React. We also used examples to practice creating and styling components.</p>
<p>Whether you’re considering a small personal project or a full-stack app for a larger user base, you now have the foundation to build these projects using React.</p>
<p>Thanks for reading!</p>
<h3 id="heading-dive-deeper-into-react">Dive deeper into React</h3>
<p>This handbook has given you a peek inside my <a target="_blank" href="https://www.amazon.com/dp/B0FRC4R8T3?tag=codesweetly00-20">Code React Sweetly book</a>. Whether you’re just starting or want to sharpen your fundamentals, the book walks you through everything from essential concepts to deploying real apps using JavaScript and TypeScript. It is practical, beginner-friendly, and designed to help you code React sweetly!</p>
<p><a target="_blank" href="https://www.amazon.com/dp/B0FRC4R8T3?tag=codesweetly00-20"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760698961658/f3f297da-1cd2-4777-b440-19b94daaa26f.jpeg" alt="A Beginner’s Guide to React: Learn JSX, Hooks, and Real-World App Development" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Become an Expert in AI-Assisted Coding – A Handbook for Developers ]]>
                </title>
                <description>
                    <![CDATA[ I’ve been running freeCodeCamp’s infrastructure for the past seven years, and I’m now convinced that experienced developers can write code 3-4x faster while maintaining quality. That's what AI-assisted development can offer. In simple terms, you can ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-become-an-expert-in-ai-assisted-coding-a-handbook-for-developers/</link>
                <guid isPermaLink="false">68b754eb90a7b8458d3a959f</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ agentic AI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mrugesh Mohapatra ]]>
                </dc:creator>
                <pubDate>Tue, 02 Sep 2025 20:34:51 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756139431600/1d0cf8b5-ba1b-4c06-ab2d-45ad5e4b4d3b.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I’ve been running freeCodeCamp’s infrastructure for the past seven years, and I’m now convinced that experienced developers can write code 3-4x faster while maintaining quality. That's what AI-assisted development can offer. In simple terms, you can be more productive with AI tools like GitHub Copilot as your coding partner. They suggest code, help you debug, and speed up repetitive tasks.</p>
<h3 id="heading-why-this-matters">Why This Matters</h3>
<p>When coding traditionally, you’re typing every line yourself, searching documentation, and figuring out syntax. With AI, you can:</p>
<ul>
<li><p>Focus on solving problems instead of remembering syntax</p>
</li>
<li><p>Learn faster by seeing good code examples in real-time</p>
</li>
<li><p>Build projects quickly without sacrificing quality</p>
</li>
</ul>
<p>Experienced developers can complete tasks faster with AI assistance. But here's the key: <strong>you need to know how to use these tools effectively</strong>. And you need a background in programming to do so.</p>
<p>Interested? Let’s dive into the world of AI-based coding tools that have taken the world by storm.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-essential-ai-terminology">Essential AI Terminology</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-ai-vs-when-to-code-yourself">When to Use AI vs When to Code Yourself</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-your-complete-learning-journey">Your Complete Learning Journey</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-generate-your-first-ai-assisted-code-quick-start">How to Generate Your First AI-Assisted Code (Quick Start)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-stage-1-foundation-getting-started-with-ai-coding">Stage 1: Foundation – Getting Started with AI Coding</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-stage-2-advanced-github-copilot-features">Stage 2: Advanced GitHub Copilot Features</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-stage-3-cli-based-ai-agents-claude-code-amp-gemini">Stage 3: CLI-Based AI Agents (Claude Code &amp; Gemini)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-stage-4-mastery-combining-tools-and-advanced-workflows">Stage 4: Mastery – Combining Tools and Advanced Workflows</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-ai-issues">Common AI Issues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-whats-next-after-completing-all-stages">What's Next After Completing All Stages?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-essential-ai-terminology">Essential AI Terminology</h2>
<p>Before we get started, let’s make sure you understand these key terms:</p>
<ul>
<li><p><strong>Tokens:</strong> Think of tokens as "word pieces" – how AI reads your code and text. Each character, word, or symbol uses tokens. Free tiers limit how many tokens you can use.</p>
</li>
<li><p><strong>Context Window:</strong> How much code/conversation the AI can "remember" at once. Like short-term memory, larger windows mean better understanding of your project.</p>
</li>
<li><p><strong>Hallucinations:</strong> When AI confidently suggests wrong information – like making up functions that don't exist. Always verify AI suggestions!</p>
</li>
<li><p><strong>Prompt:</strong> Your instructions to the AI – comments, questions, or requests that guide what code it generates.</p>
</li>
</ul>
<h2 id="heading-when-to-use-ai-vs-when-to-code-yourself">When to Use AI vs When to Code Yourself</h2>
<p><strong>Use AI for:</strong></p>
<ul>
<li><p>Writing boilerplate code (getters, setters, basic CRUD)</p>
</li>
<li><p>Learning new frameworks or syntax</p>
</li>
<li><p>Writing tests and documentation</p>
</li>
<li><p>Refactoring repetitive patterns</p>
</li>
<li><p>Getting unstuck on syntax errors</p>
</li>
</ul>
<p><strong>Code yourself when you’re:</strong></p>
<ul>
<li><p>Designing system architecture</p>
</li>
<li><p>Making security-critical decisions</p>
</li>
<li><p>Writing complex business logic</p>
</li>
<li><p>Learning new concepts (first time)</p>
</li>
<li><p>Working on performance-critical optimizations</p>
</li>
</ul>
<p><strong>The Golden Rule:</strong> Use AI to speed up implementation, but keep architectural decisions to yourself. AI is excellent at "how", but you decide "what" and "why."</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before starting this tutorial, you should have:</p>
<ul>
<li><p><strong>Basic programming experience</strong> – You can write simple programs in any language</p>
</li>
<li><p><strong>A code editor installed</strong> – VS Code is recommended (free from <a target="_blank" href="http://code.visualstudio.com/">code.visualstudio.com</a>)</p>
</li>
<li><p><strong>Basic Git knowledge</strong> – You know how to commit and push code</p>
</li>
<li><p><strong>Free to start</strong> – Many tools now have generous free tiers, and paid plans start around $10-20/month</p>
</li>
</ul>
<h2 id="heading-your-complete-learning-journey">Your Complete Learning Journey</h2>
<p>This comprehensive tutorial is structured as a step-by-step program to transform you into an AI-assisted development expert:</p>
<p>Note: To keep the tutorial approachable, we’ll just focus on a core handful of tools. But you should research and explore more tools that might fit your specific needs beyond the ones we use here.</p>
<h3 id="heading-your-learning-path">Your Learning Path:</h3>
<p>You'll progress through 4 stages: mastering GitHub Copilot basics, unlocking advanced features like chat modes and agents, exploring CLI tools (Claude Code &amp; Gemini), and finally combining multiple tools strategically for complete project workflows.</p>
<p>First, let's quickly see how you can generate your first AI code snippet.</p>
<h2 id="heading-how-to-generate-your-first-ai-assisted-code-quick-start">How to Generate Your First AI-Assisted Code (Quick Start)</h2>
<p>Let's start with the absolute basics. Don't worry about choosing the "perfect" tool – you can always switch later. Here's how to get started:</p>
<h3 id="heading-github-copilot-recommended-for-beginners">GitHub Copilot (Recommended for Beginners)</h3>
<p>You can install GitHub Copilot by following these steps:</p>
<ol>
<li><p>Open VS Code</p>
</li>
<li><p>Click the Extensions icon (or press Ctrl+Shift+X)</p>
</li>
<li><p>Search for "GitHub Copilot"</p>
</li>
<li><p>Click "Install"</p>
</li>
<li><p>Sign in with your GitHub account</p>
</li>
</ol>
<p>GitHub Copilot has a free tier (2000 code completions + 50 chat requests per month), which should be enough for this experiment.</p>
<p><strong>TIP:</strong> Students, teachers, and OSS maintainers <a target="_blank" href="https://docs.github.com/en/copilot/how-tos/manage-your-account/getting-free-access-to-copilot-pro-as-a-student-teacher-or-maintainer">can get the Pro plan for free</a>, which provides unlimited usage instead of the free tier limits.</p>
<h3 id="heading-your-first-ai-suggestion">Your First AI Suggestion</h3>
<p>Once installed, create a new file called <code>test.js</code> and type:</p>
<pre><code class="lang-plaintext">// function to calculate the area of a circle
</code></pre>
<p>Press Enter and wait. You'll see gray text appear – that's your AI suggestion! Press Tab to accept it.</p>
<p>That’s it! You’ve just gotten your first AI suggestion! Isn’t that cool?</p>
<h2 id="heading-stage-1-foundation-getting-started-with-ai-coding">Stage 1: Foundation – Getting Started with AI Coding</h2>
<h3 id="heading-step-1-understanding-your-options">Step 1: Understanding Your Options</h3>
<p>Think of AI coding assistants like different types of helpful friends and colleagues. Let’s cover a few:</p>
<p><strong>IDE-based:</strong> Some tools are designed to work with familiar code editors or are a standalone fork of editors like VS Code. For example:</p>
<ul>
<li><p><strong>GitHub Copilot (VS Code Extension)</strong> – An AI coding assistant from GitHub, works directly in VS Code with tab completion and chat features</p>
</li>
<li><p><strong>Cursor (Standalone)</strong> – VS Code fork with enhanced agent modes, faster autonomous coding, and better handling of large codebase refactoring</p>
</li>
<li><p><strong>Windsurf (Standalone or VS Code Extension)</strong> – Focuses on collaborative AI development with real-time suggestions and team features</p>
</li>
<li><p><strong>Zed</strong> – High-performance editor with built-in AI assistance and fast rendering</p>
</li>
</ul>
<p><strong>CLI-based:</strong> Some tools are CLI-based, which you can launch within your terminal app:</p>
<ul>
<li><p><strong>Claude Code</strong> – Anthropic's terminal AI for autonomous development sessions and complex reasoning</p>
</li>
<li><p><strong>Gemini</strong> – Google's CLI tool with large context windows and multimodal capabilities (images, documents)</p>
</li>
<li><p><strong>OpenCode</strong> – Open-source alternative with customizable models and local processing options</p>
</li>
<li><p><strong>Cursor CLI</strong> – Terminal version of Cursor for command-line AI assistance</p>
</li>
</ul>
<p><strong>UI-based and Background Agents:</strong> Besides these, there are also background agents and tools that can operate entirely in the background, such as performing pull-request reviews and more.</p>
<p>For example, both ChatGPT and Claude's desktop app can edit files on your local file system if you set them up. Similarly, some cloud-based agents can "run in the background" to complete your instructions. We will exclude these from the scope of this guide.</p>
<h3 id="heading-step-2-making-your-choice-amp-learning-automatic-suggestions-tab-completion">Step 2: Making Your Choice &amp; Learning Automatic Suggestions (Tab Completion)</h3>
<p>For your first stage, I recommend starting with either GitHub Copilot. You can always switch to the tool that fits your needs after you learn the basics.</p>
<h3 id="heading-step-3-step-by-step-setup">Step 3: Step-by-Step Setup</h3>
<h4 id="heading-how-to-set-up-github-copilot-you-can-skip-this-if-you-already-followed-the-quick-start-earlier">How to Set Up GitHub Copilot (You can skip this if you already followed the Quick Start earlier)</h4>
<ol>
<li><p><strong>Open VS Code.</strong> If you don't have it, download from <a target="_blank" href="https://code.visualstudio.com/">code.visualstudio.com</a>.</p>
</li>
<li><p><strong>Install the Extension</strong></p>
<ul>
<li><p>Press <code>Ctrl+Shift+X</code> (Windows/Linux) or <code>Cmd+Shift+X</code> (Mac)</p>
</li>
<li><p>Type "GitHub Copilot" in the search box</p>
</li>
<li><p>Click the blue "Install" button</p>
</li>
<li><p>You'll see a pop-up asking you to sign in</p>
</li>
</ul>
</li>
<li><p><strong>Sign In</strong></p>
<ul>
<li><p>Click "Sign in to GitHub"</p>
</li>
<li><p>Your browser will open</p>
</li>
<li><p>Log in with your GitHub account (create one free at <a target="_blank" href="http://github.com/">github.com</a> if needed)</p>
</li>
<li><p>Click "Authorize GitHub Copilot"</p>
</li>
</ul>
</li>
<li><p><strong>Start using Copilot</strong></p>
<ul>
<li>Back in VS Code, you'll see "GitHub Copilot is ready"</li>
</ul>
</li>
</ol>
<h3 id="heading-step-4-mastering-tab-completion">Step 4: Mastering Tab Completion</h3>
<p>Let's make sure it's working. Create a new file: <code>hello.py</code>. Type this comment and press Enter:</p>
<pre><code class="lang-plaintext"># function to greet a user by name
</code></pre>
<p>Wait 1-2 seconds. You should see gray text appear. Just press <code>Tab</code> to accept the suggestion.</p>
<p><strong>What you should see:</strong></p>
<pre><code class="lang-plaintext"># function to greet a user by name
def greet_user(name):
    return f"Hello, {name}!"
</code></pre>
<p>If you see this, congratulations! You're now using AI to help you write code.</p>
<p>If you’re having setup issues you can check the <a class="post-section-overview" href="#heading-troubleshooting-quick-reference">Troubleshooting Quick Reference</a> for solutions.</p>
<h3 id="heading-step-5-essential-keyboard-shortcuts-amp-first-practice">Step 5: Essential Keyboard Shortcuts &amp; First Practice</h3>
<p>Here are the only shortcuts you need for your first week:</p>
<p><strong>The Basics:</strong></p>
<ul>
<li><p><code>Tab</code> – Accept the AI suggestion (use this the most!)</p>
</li>
<li><p><code>Esc</code> – Dismiss the suggestion (when you don't want it)</p>
</li>
</ul>
<p>When you're ready for more, try these:</p>
<p><strong>Windows/Linux:</strong></p>
<ul>
<li><p><code>Alt+]</code> – See the next suggestion</p>
</li>
<li><p><code>Alt+[</code> – See the previous suggestion</p>
</li>
<li><p><code>Ctrl+Enter</code> – See all suggestions in a panel</p>
</li>
</ul>
<p><strong>macOS:</strong></p>
<ul>
<li><p><code>Option+]</code> (or <code>Alt+]</code>) – See the next suggestion</p>
</li>
<li><p><code>Option+[</code> (or <code>Alt+[</code>) – See the previous suggestion</p>
</li>
<li><p><code>Ctrl+Enter</code> – See all suggestions in a panel</p>
</li>
</ul>
<h3 id="heading-stage-1-practice-exercise">Stage 1 Practice Exercise</h3>
<h4 id="heading-exercise-build-a-simple-todo-app">Exercise: Build a Simple Todo App</h4>
<ol>
<li><p>Create a new file called <code>todo.js</code></p>
</li>
<li><p>Start with this comment: <code>// TODO app with add, remove, and list functions</code></p>
</li>
<li><p>Add this comment and wait for AI suggestions: <code>// function to add a new todo item</code></p>
</li>
<li><p>Accept the suggestion with Tab if they look good to you</p>
</li>
<li><p>Continue adding comments for remove and list functions</p>
</li>
<li><p>Test your functions to make sure they work</p>
</li>
</ol>
<p><strong>Goal:</strong> Learn to "converse" with AI through clear comments and build confidence accepting/rejecting suggestions.</p>
<p>Need help? See the <a class="post-section-overview" href="#heading-troubleshooting-quick-reference">Troubleshooting Quick Reference</a> for common issues and solutions.</p>
<h3 id="heading-ready-for-the-next-stage-before-moving-on-make-sure-you-can">Ready for the next stage? Before moving on, make sure you can:</h3>
<pre><code class="lang-plaintext">- [ ] Get AI suggestions by typing comments
- [ ] Accept suggestions with Tab and dismiss with Esc
- [ ] Use Alt+] and Alt+[ to see different suggestions
- [ ] Write basic functions with AI help
</code></pre>
<p>If you're comfortable with these basics, you're ready to learn more powerful Copilot features.</p>
<h2 id="heading-stage-2-advanced-github-copilot-features">Stage 2: Advanced GitHub Copilot Features</h2>
<h3 id="heading-step-6-getting-better-ai-suggestions">Step 6: Getting Better AI Suggestions</h3>
<p>Now that you know the basics, let's learn how to get <em>much better</em> suggestions from your AI. The secret is understanding what your AI can see.</p>
<h4 id="heading-what-your-ai-assistant-sees">What Your AI Assistant Sees</h4>
<p>Think of your AI assistant like a helpful friend looking over your shoulder. It can see:</p>
<ol>
<li><p><strong>What you're typing right now</strong> – Your current file</p>
</li>
<li><p><strong>Other open tabs</strong> – Files you have open (this is important!)</p>
</li>
<li><p><strong>Your project structure</strong> – Folder and file names</p>
</li>
<li><p><strong>Your comments</strong> – This is how you "talk" to the AI</p>
</li>
</ol>
<h4 id="heading-the-neighboring-tabs-trick">The "Neighboring Tabs" Trick</h4>
<p>Here's a pro tip that will save you hours: <strong>Keep related files open in tabs</strong>.</p>
<p><strong>Example:</strong> If you're writing a React component:</p>
<ul>
<li><p>Have your component file open (<code>Button.jsx</code>)</p>
</li>
<li><p>Also, open your CSS file (<code>Button.css</code>)</p>
</li>
<li><p>Keep your test file visible too (<code>Button.test.js</code>)</p>
</li>
</ul>
<p>You can then share these additional files as context with the AI in several ways:</p>
<ul>
<li><p><strong>@mention files:</strong> Type <code>@filename.js</code> in chat to reference specific files</p>
</li>
<li><p><strong>Use @workspace:</strong> This chat participant can see all files in your project</p>
</li>
<li><p><strong>Drag and drop:</strong> Simply drag files from the explorer into the chat window</p>
</li>
<li><p><strong>Select code:</strong> Highlight code and right-click "Ask Copilot" to include it in context</p>
</li>
</ul>
<p>The AI uses these open files to understand your project structure and suggest more relevant code that matches your existing patterns.</p>
<h3 id="heading-step-7-quality-control-amp-best-practices">Step 7: Quality Control &amp; Best Practices</h3>
<h4 id="heading-understanding-ai-limitations">Understanding AI Limitations</h4>
<p>AI is powerful but it’s not perfect. Here are the key things to watch for:</p>
<p><strong>Common AI Mistakes:</strong></p>
<ol>
<li><p>Made-up functions: for example, <code>const result = array.superSort();</code> doesn't exist!</p>
</li>
<li><p>Wrong parameters: for example, <code>greetUser("John", "Doe");</code> when function expects <code>greetUser(name)</code></p>
</li>
<li><p>Overcomplicated solutions: for example, <code>const isEven = (num) =&gt; num.toString(2).slice(-1) === "0";</code> – just use <code>num % 2 === 0</code></p>
</li>
</ol>
<p>Quick quality checklist:</p>
<pre><code class="lang-plaintext">- [ ] Test the code - does it actually work?
- [ ] Read it - does it make logical sense?
- [ ] Check basics - are all functions/variables defined?
- [ ] Trust instincts - if it feels wrong, investigate
</code></pre>
<h4 id="heading-security-essentials">Security Essentials</h4>
<p>Before accepting AI suggestions, make sure you check for these security issues:</p>
<pre><code class="lang-plaintext">- [ ] No hardcoded passwords or API keys
- [ ] User input is validated
- [ ] No eval() with user data
- [ ] Error messages don't expose sensitive info
</code></pre>
<h4 id="heading-better-prompt-writing">Better Prompt Writing</h4>
<p>Here’s a formula for writing solid prompts: What + How + Return type.</p>
<pre><code class="lang-plaintext">// ❌ Vague: "make function"
// ✅ Clear: "function to validate email format using regex, returns boolean"
</code></pre>
<h4 id="heading-repository-level-customization-with-copilot-instructions">Repository-Level Customization with Copilot Instructions</h4>
<p>GitHub Copilot now supports repository-level customization through <code>.github/copilot-instructions.md</code> files. This feature helps Copilot understand your project's specific patterns and conventions.</p>
<p>Here’s how to set up Copilot instructions:</p>
<pre><code class="lang-plaintext"># Create GitHub directory if it doesn't exist
mkdir -p .github
touch .github/copilot-instructions.md
</code></pre>
<p>Example <a target="_blank" href="http://copilot-instructions.md/">copilot-instructions.md</a> file:</p>
<pre><code class="lang-plaintext"># Copilot Instructions

## Code Style

- Use React functional components with hooks
- Prefer TypeScript over JavaScript for new files
- Use Tailwind CSS for styling
- Follow the existing file structure in `/src/components`

## Testing

- Write tests with React Testing Library
- Place test files in `__tests__` directories
- Use descriptive test names that explain the behavior

## API Patterns

- Use custom hooks for API calls
- Handle loading and error states consistently
- Use React Query for data fetching

## Naming Conventions

- Components: PascalCase (e.g., `UserProfile.tsx`)
- Hooks: camelCase starting with 'use' (e.g., `useUserData.ts`)
- Utilities: camelCase (e.g., `formatDate.ts`)
</code></pre>
<p><strong>What this enables:</strong></p>
<ul>
<li><p>Copilot suggests code that matches your project patterns</p>
</li>
<li><p>Automatically follows your naming conventions</p>
</li>
<li><p>Suggests appropriate testing approaches</p>
</li>
<li><p>Understands your preferred libraries and frameworks</p>
</li>
</ul>
<p><strong>Best practices:</strong></p>
<ul>
<li><p>Keep instructions clear and specific</p>
</li>
<li><p>Update them as your project standards evolve</p>
</li>
<li><p>Include examples of preferred patterns</p>
</li>
<li><p>Mention libraries and frameworks you use</p>
</li>
</ul>
<h3 id="heading-step-8-unlocking-advanced-copilot-features">Step 8: Unlocking Advanced Copilot Features</h3>
<h4 id="heading-understanding-your-options">Understanding Your Options</h4>
<p>GitHub Copilot offers multiple ways to get AI help:</p>
<ol>
<li><p><strong>Tab Completion</strong> (what you've been using) – Suggestions while typing</p>
</li>
<li><p><strong>Chat Mode</strong> – Have conversations with AI about your code</p>
</li>
<li><p><strong>Edit Mode</strong> – Ask AI to modify existing code</p>
</li>
<li><p><strong>Agent Mode</strong> – Let AI work autonomously on big tasks</p>
</li>
</ol>
<p>We’ll discuss these modes in more detail below so you know how they work and when you should use them.</p>
<h4 id="heading-model-selection">Model Selection</h4>
<p>Copilot now offers different AI models for different needs:</p>
<p>Free with subscription:</p>
<ul>
<li><p><strong>GPT-4.1</strong> – Default model with solid all-around performance</p>
</li>
<li><p><strong>GPT-4</strong> – Reliable for most coding tasks</p>
</li>
</ul>
<p>Premium models (limited monthly usage):</p>
<ul>
<li><p><strong>Claude 3.5 Sonnet</strong> – Great for complex logic</p>
</li>
<li><p><strong>GPT-5</strong> – Latest and most capable</p>
</li>
<li><p><strong>Gemini 2.0 Flash</strong> – Very fast responses</p>
</li>
</ul>
<p><strong>How to switch models:</strong> Click the model dropdown in Chat view</p>
<p><strong>Tip:</strong> Start with free models (GPT-4.1) for learning, and save premium models for complex problems.</p>
<h4 id="heading-github-copilot-limitations">GitHub Copilot Limitations</h4>
<p>Here are some important things to consider when you’re using AI to help you out with your coding:</p>
<ul>
<li><p><strong>Internet dependency</strong> – Requires stable connection for suggestions</p>
</li>
<li><p><strong>Context limitations</strong> – Only sees open files, not your entire project structure</p>
</li>
<li><p><strong>Free tier limits</strong> – 2,000 completions and 50 chat requests per month</p>
</li>
<li><p><strong>Code quality varies</strong> – Always review suggestions, especially for security-sensitive code</p>
</li>
<li><p><strong>Learning curve</strong> – Takes time to write effective prompts for complex tasks</p>
</li>
<li><p><strong>Privacy considerations</strong> – Your code is sent to GitHub's servers (check your organization's policies)</p>
</li>
</ul>
<h4 id="heading-basic-chat-vs-suggestions">Basic Chat vs Suggestions</h4>
<p>So you might be wondering - when should you use tab completion vs when should you use chat? It’s best to use tab completion for writing new functions, quick syntax help, and completing patterns. You can use chat for explaining existing code, getting help with errors, and planning your approach to problems.</p>
<p><strong>Try it:</strong> Open Chat (Ctrl+Shift+I) and ask: "What does this function do?" while selecting code.</p>
<h3 id="heading-step-9-mastering-chat-and-agent-modes">Step 9: Mastering Chat and Agent Modes</h3>
<h4 id="heading-the-three-chat-modes">The Three Chat Modes</h4>
<ol>
<li><strong>Ask Mode (Default)</strong> – for questions and explanations:</li>
</ol>
<pre><code class="lang-plaintext">"What does this function do?"
"How can I optimize this code?"
"Explain this error message"
</code></pre>
<ol start="2">
<li><strong>Edit Mode</strong> – For making changes to existing code:</li>
</ol>
<pre><code class="lang-plaintext">"Refactor this to use async/await"
"Add error handling to all API calls"
"Convert this to TypeScript"
</code></pre>
<ul>
<li><p>Shows inline diffs before applying changes</p>
</li>
<li><p>Works across multiple files</p>
</li>
<li><p>Great for systematic refactoring</p>
</li>
</ul>
<ol start="3">
<li><strong>Agent Mode</strong> – For autonomous development:</li>
</ol>
<pre><code class="lang-plaintext">"Create a REST API with authentication"
"Build a todo app with React and testing"
"Migrate this codebase from Vue 2 to Vue 3"
</code></pre>
<ul>
<li><p>Press <code>Cmd+Shift+I</code> (Mac) or <code>Ctrl+Shift+Alt+I</code> (Linux) or <code>Ctrl+Shift+I</code> (Windows)</p>
</li>
<li><p>Works independently for hours</p>
</li>
<li><p>Installs packages, creates files, runs tests automatically</p>
</li>
</ul>
<h4 id="heading-when-to-use-each-mode">When to Use Each Mode</h4>
<p>Each mode has its particular use cases. Use ask mode when you’re learning new concepts, you want to understand existing code, for getting explanations, and for planning approaches.</p>
<p>Use edit mode when you’re refactoring existing code, applying consistent changes, adding features to existing functions, or for style/pattern updates.</p>
<p>Agent mode is useful for building complete features (30+ minutes of work), setting up new projects, large-scale refactoring, and for when you want to work on other things while AI codes.</p>
<h4 id="heading-agent-mode-examples">Agent Mode Examples</h4>
<p>Small agent task (15 minutes):</p>
<pre><code class="lang-plaintext">"Add user authentication to my Express app"
</code></pre>
<p>What the agent generated:</p>
<pre><code class="lang-plaintext">// middleware/auth.js
const jwt = require('jsonwebtoken');

const authenticateToken = (req, res, next) =&gt; {
  const authHeader = req.headers['authorization'];
  const token = authHeader &amp;&amp; authHeader.split(' ')[1];

  if (!token) return res.sendStatus(401);

  jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) =&gt; {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
};

// routes/auth.js
router.post('/login', async (req, res) =&gt; {
  // Authentication logic with bcrypt
  const accessToken = jwt.sign({username: user.username}, process.env.ACCESS_TOKEN_SECRET);
  res.json({accessToken: accessToken});
});
</code></pre>
<p><strong>Key issues I found:</strong> The agent initially forgot to hash passwords and didn't include refresh tokens. This required one iteration to fix security gaps and add proper error handling.</p>
<p>Large agent task (4+ hours):</p>
<pre><code class="lang-plaintext">"Modernize this React class-based app to hooks with TypeScript"
</code></pre>
<p>What the agent generated:</p>
<pre><code class="lang-plaintext">// Before (Class component)
class UserProfile extends React.Component {
  constructor(props) {
    this.state = { user: null, loading: true };
  }
  // ... lifecycle methods
}

// After (Hooks + TypeScript)
interface User {
  id: number;
  name: string;
  email: string;
}

const UserProfile: React.FC = () =&gt; {
  const [user, setUser] = useState&lt;User | null&gt;(null);
  const [loading, setLoading] = useState(true);

  useEffect(() =&gt; {
    fetchUser().then(setUser).finally(() =&gt; setLoading(false));
  }, []);

  return &lt;div&gt;{loading ? 'Loading...' : user?.name}&lt;/div&gt;;
};
</code></pre>
<p><strong>Key issuesI found:</strong> the agent successfully updated 47 files, but initially had typing issues with event handlers and needed refinement of generic types. The automated tests also required manual review to ensure proper TypeScript coverage.</p>
<h4 id="heading-using-chat-participants">Using Chat Participants</h4>
<p>Chat participants are specialized AI assistants that have access to specific parts of your development environment. Think of them as experts in different areas who can help with targeted tasks.</p>
<p>They’re basically AI helpers prefixed with <code>@</code> that have special knowledge and capabilities:</p>
<ul>
<li><p><strong>@workspace</strong> has access to your entire project structure, and can search files and understand relationships between components. Use <code>@workspace</code> when you need project-wide analysis: "Find all API endpoints in this project" or "Show me where user authentication is implemented."</p>
</li>
<li><p><strong>@terminal</strong> knows about command-line operations, and can suggest shell commands and explain terminal output. Use <code>@terminal</code> for command-line help: "What command runs the tests?" or "How do I build this project for production?"</p>
</li>
<li><p><strong>@vscode</strong> is an expert in VS Code features, and can help with settings, debugging, and editor configuration. Use <code>@vscode</code> for editor assistance: "Set up debugging for Node.js" or "Configure auto-formatting for this project."</p>
</li>
</ul>
<p><strong>Example usage:</strong></p>
<pre><code class="lang-plaintext">@workspace Can you find all the database models in this project?
@terminal What's the command to install dependencies and start the dev server?
@vscode How do I set up breakpoints for debugging this Express app?
</code></pre>
<h3 id="heading-step-10-power-user-features-and-advanced-workflows">Step 10: Power User Features and Advanced Workflows</h3>
<p>Beyond the core Copilot features you've learned, there are specialized tools and commands that can supercharge your productivity. These features go beyond basic chat modes and model selection, focusing on complex multi-file operations and advanced automation.</p>
<h4 id="heading-advanced-slash-commands">Advanced Slash Commands</h4>
<pre><code class="lang-plaintext">/doc - Generate documentation
/explain - Detailed code explanation
/fix - Fix errors in selected code
/tests - Generate unit tests
/new - Create new project structure
</code></pre>
<h4 id="heading-multi-file-operations">Multi-File Operations</h4>
<p><strong>Using # References:</strong></p>
<p>The <code>#</code> symbol creates specific references that tell Copilot exactly what to focus on. These references work like precise pointers to different parts of your project:</p>
<ul>
<li><p><strong>#file:filename</strong>: References a specific file: <code>#file:UserModel.js</code></p>
</li>
<li><p><strong>#codebase</strong>: References your entire project codebase for searching</p>
</li>
<li><p><strong>#selection</strong>: References currently selected code</p>
</li>
<li><p><strong>#editor</strong>: References the currently active file</p>
</li>
</ul>
<pre><code class="lang-plaintext">"Update #file:UserModel.js to include timestamps"
"Search #codebase for all database queries"  
"Refactor #selection to use modern JavaScript syntax"
"Add error handling to #editor for all API calls"
</code></pre>
<p>These references help Copilot understand exactly where to look and what to change, making multi-file operations much more precise.</p>
<p><strong>Drag and Drop:</strong></p>
<p>Drag and drop is one of the most intuitive ways to provide context to Copilot. You can simply drag files from the VS Code explorer directly into the chat window, and Copilot will instantly understand their contents and structure.</p>
<p>This feature is particularly useful when you're working on related components and need the AI to understand how different files connect together. Copilot remembers these file relationships throughout your conversation, so you don't need to re-upload files when continuing the same discussion.</p>
<p>This context persistence works across multiple chat sessions, making it easy to pick up where you left off on complex multi-file projects.</p>
<h3 id="heading-stage-2-practice-exercises">Stage 2 Practice Exercises</h3>
<h4 id="heading-exercise-1-chat-mode-practice">Exercise 1: Chat Mode Practice</h4>
<ol>
<li><p>Use Ask Mode to understand a complex function</p>
</li>
<li><p>Switch to Edit Mode to refactor it</p>
</li>
<li><p>Compare the approaches</p>
</li>
</ol>
<h4 id="heading-exercise-2-agent-mode-project">Exercise 2: Agent Mode Project</h4>
<ol>
<li><p>Start Agent Mode (<code>Shift+Cmd+I</code>)</p>
</li>
<li><p>Request: "Create a simple todo app with testing"</p>
</li>
<li><p>Watch the autonomous development process</p>
</li>
<li><p>Review the generated code</p>
</li>
</ol>
<h4 id="heading-exercise-3-advanced-features">Exercise 3: Advanced Features</h4>
<ol>
<li><p>Use @ participants for project questions</p>
</li>
<li><p>Experiment with slash commands</p>
</li>
<li><p>Practice multi-file operations</p>
</li>
</ol>
<h3 id="heading-ready-for-cli-tools">Ready for CLI Tools?</h3>
<p>You've now learned the basics of GitHub Copilot in VS Code! CLI tools like Claude Code and Gemini offer even more power for terminal-based development.</p>
<p>If you’re interested in terminal AI you can continue to Stage 3 just below. If you prefer to stick with VS Code, just skip to Stage 4 for advanced workflows.</p>
<h2 id="heading-stage-3-cli-based-ai-agents-claude-code-amp-gemini">Stage 3: CLI-Based AI Agents (Claude Code &amp; Gemini)</h2>
<h3 id="heading-step-11-meet-claude-code-your-terminal-ai-assistant">Step 11: Meet Claude Code – Your Terminal AI Assistant</h3>
<h4 id="heading-what-is-claude-code">What is Claude Code?</h4>
<p>Remember how GitHub Copilot helps you in VS Code? Claude Code does the same thing, but in your terminal.</p>
<p>Instead of typing in VS Code and getting suggestions, you type in your terminal and have conversations with AI. It's like having a coding buddy right in your command line.</p>
<h4 id="heading-simple-example">Simple example:</h4>
<p>In VS Code with Copilot:</p>
<pre><code class="lang-plaintext">// create a function to validate email
[AI suggests code]
</code></pre>
<p>In Terminal with Claude Code:</p>
<pre><code class="lang-plaintext">claude
&gt; Create a function to validate email addresses
[AI writes the code for you]
</code></pre>
<p>So when should you use VS Code/Copilot and when should you use Claude Code?</p>
<p><strong>Claude Code is great if you:</strong></p>
<ul>
<li><p>Like working in the terminal</p>
</li>
<li><p>Want to have AI conversations about code</p>
</li>
<li><p>Need help with command-line tasks</p>
</li>
<li><p>Want more control over AI interactions</p>
</li>
</ul>
<p><strong>Stick with VS Code Copilot if you:</strong></p>
<ul>
<li><p>Prefer visual editors</p>
</li>
<li><p>Are happy with your current workflow</p>
</li>
<li><p>Don't spend much time in terminal</p>
</li>
</ul>
<h4 id="heading-pricing">Pricing</h4>
<p>Claude Code requires Claude Pro (20/month), or ClaudeMax (100/month) subscription, or pay-per-use with API credits.</p>
<h4 id="heading-claude-code-limitations">Claude Code Limitations</h4>
<p>Here are some important considerations if you’re planning to use Claude Code:</p>
<ul>
<li><p><strong>Paid only</strong> – No free tier, requires Claude Pro subscription or API credits</p>
</li>
<li><p><strong>Terminal-based</strong> – Less visual than IDE-integrated tools</p>
</li>
<li><p><strong>Learning curve</strong> – Requires comfort with command-line interfaces</p>
</li>
<li><p><strong>Context management</strong> – You need to manage conversation context manually</p>
</li>
<li><p><strong>Internet dependency</strong> – Requires stable connection for all operations</p>
</li>
<li><p><strong>Session limits</strong> – Long autonomous sessions consume significant API credits</p>
</li>
</ul>
<h4 id="heading-installation">Installation</h4>
<p>Recommended (all platforms):</p>
<pre><code class="lang-plaintext">npm install -g @anthropic-ai/claude-code
</code></pre>
<p>Alternative installs:</p>
<ul>
<li><p><strong>macOS/Linux</strong>: <code>curl -fsSL https://claude.ai/install.sh | bash</code></p>
</li>
<li><p><strong>Windows</strong>: <code>irm https://claude.ai/install.ps1 | iex</code></p>
</li>
</ul>
<h4 id="heading-basic-usage">Basic Usage</h4>
<p><strong>Interactive Mode (Recommended):</strong></p>
<p>Interactive mode is Claude Code's primary interface where you have real-time conversations with the AI. Unlike one-shot commands that execute once and exit, interactive mode creates a persistent session where you can ask follow-up questions, iterate on solutions, and build complex projects over time.</p>
<p>Interactive mode is recommended because:</p>
<ul>
<li><p><strong>Context persistence:</strong> Claude remembers the entire conversation and project context</p>
</li>
<li><p><strong>Iterative development:</strong> You can refine requests and build on previous responses</p>
</li>
<li><p><strong>Real-time collaboration:</strong> Ask questions, get explanations, and modify approaches as you work</p>
</li>
<li><p><strong>Session resumption:</strong> Continue previous conversations with <code>claude --resume</code></p>
</li>
</ul>
<p><strong>Other Modes Available:</strong></p>
<ul>
<li><p><strong>One-shot mode:</strong> Single command execution (explained below)</p>
</li>
<li><p><strong>Agent mode:</strong> Autonomous development sessions that can work for hours independently</p>
</li>
</ul>
<ol>
<li>Navigate to your project:</li>
</ol>
<pre><code class="lang-plaintext">cd your-project
claude
</code></pre>
<ol start="2">
<li>Start conversing naturally:</li>
</ol>
<pre><code class="lang-plaintext">Claude Code &gt; analyze this codebase and suggest improvements

Claude Code &gt; now help me refactor the user authentication

Claude Code &gt; add unit tests for the payment module
</code></pre>
<ol start="3">
<li>Continue previous session:</li>
</ol>
<pre><code class="lang-plaintext">claude --resume
</code></pre>
<p><strong>One-shot Commands (for quick tasks):</strong></p>
<p>One-shot commands are single-execution commands that perform a specific task and then exit. Unlike interactive mode, these don't maintain conversation context – they're perfect for quick, standalone tasks.</p>
<p><strong>What are One-shot Commands?</strong></p>
<p>These are commands you run with a specific instruction directly from your terminal, without entering an interactive session. Claude executes the request and provides results immediately.</p>
<p><strong>When to Use One-shot Commands:</strong></p>
<ul>
<li><p>Quick analysis or code reviews</p>
</li>
<li><p>Simple file modifications</p>
</li>
<li><p>Automated scripts and CI/CD integration</p>
</li>
<li><p>When you need a single, specific answer</p>
</li>
</ul>
<p><strong>Examples:</strong></p>
<pre><code class="lang-plaintext">claude "analyze this codebase and suggest improvements"
claude "fix all TypeScript errors in src/"
claude "generate unit tests for utils.js"
claude "explain what this function does" --file src/auth.js
</code></pre>
<p>The key difference is that one-shot commands don't remember context between runs, while interactive mode maintains full conversation history and project understanding.</p>
<p><strong>Interactive vs Autonomous Sessions:</strong></p>
<p>Within interactive mode, you can choose between collaborative and autonomous approaches:</p>
<p><strong>Interactive Session (collaborative):</strong></p>
<pre><code class="lang-plaintext">Claude Code &gt; I'm building user authentication. What approach should we take?

You: Use JWT tokens with refresh token rotation

Claude Code &gt; implement JWT authentication with refresh tokens
[Shows you the implementation step by step]

Claude Code &gt; shall I also add password reset functionality?

You: Yes, use email-based reset
</code></pre>
<p><strong>Autonomous Session (hands-off development):</strong></p>
<pre><code class="lang-plaintext">Claude Code &gt; Build a complete user management system with authentication, profiles, preferences, and admin features. Use best practices for security and testing.

[Claude works for hours autonomously, providing periodic updates]
[Final result: Complete user management system ready for production]
</code></pre>
<p><strong>When to Use Each:</strong> Use interactive sessions when learning or when you want control over decisions. Use autonomous sessions for well-defined tasks where you trust Claude to make good choices independently.</p>
<h4 id="heading-key-features">Key Features</h4>
<p><strong>Thinking Modes (use in interactive session):</strong></p>
<p>Thinking modes are special commands that tell Claude how deeply to analyze before responding. You choose these modes manually based on your problem's complexity.</p>
<p><strong>When to Use Each Mode:</strong></p>
<ul>
<li><p><code>think</code> – Quick analysis for straightforward tasks: "think: review this function for bugs"</p>
</li>
<li><p><code>think hard</code> – Deeper reasoning for complex logic: "think hard: optimize this algorithm"</p>
</li>
<li><p><code>think harder</code> – Complex problem solving with multiple considerations: "think harder: design a scalable database schema"</p>
</li>
<li><p><code>ultrathink</code> – Maximum depth analysis for architectural decisions: "ultrathink: evaluate microservices vs monolith for this project"</p>
</li>
</ul>
<p><strong>How They Work:</strong></p>
<p>Claude shows you its reasoning process with longer thinking modes. You'll see step-by-step analysis before getting the final answer. Higher thinking modes take longer but provide more thorough solutions.</p>
<p><strong>Choosing the Right Mode:</strong></p>
<p>Use <code>think</code> for quick code reviews, <code>think hard</code> for debugging complex issues, <code>think harder</code> for system design problems, and <code>ultrathink</code> for major architectural decisions that affect your entire project.</p>
<h4 id="heading-project-level-customization-with-claudemd">Project-Level Customization with Claude.md</h4>
<p>One of Claude Code's most powerful features is project-level customization using <code>.claude/CLAUDE.md</code> files. This lets you give Claude context about your specific project, coding standards, and preferences.</p>
<p>Set up CLAUDE.md like this:</p>
<pre><code class="lang-plaintext"># Create project-level configuration
mkdir -p .claude
touch .claude/CLAUDE.md
</code></pre>
<p>Here’s an example CLAUDE.md file:</p>
<pre><code class="lang-plaintext"># Project Context

This is a Node.js REST API using Express and PostgreSQL.

## Coding Standards

- Use async/await, never callbacks
- All database queries use Prisma ORM
- Write tests with Jest for all new functions
- Follow RESTful conventions

## Project Structure

- `/src/routes` - API endpoints
- `/src/models` - Database models
- `/src/middleware` - Express middleware
- `/tests` - Unit and integration tests

## Preferences

- Use TypeScript for all new files
- Prefer functional programming patterns
- Include JSDoc comments for all functions
</code></pre>
<p>This helps Claude understand your project structure automatically. It also helps Claude follow your specific coding standards, suggest appropriate patterns for your tech stack, and remember your preferences across sessions.</p>
<p><strong>Pro tip:</strong> Update your CLAUDE.md as your project evolves to keep Claude's suggestions relevant and accurate.</p>
<h4 id="heading-claude-code-autonomous-development-sessions">Claude Code Autonomous Development Sessions</h4>
<p>Here’s an example of a multi-hour autonomous development session:</p>
<pre><code class="lang-plaintext">cd your-project
claude
</code></pre>
<p><strong>Your prompt:</strong> "Build a scalable GraphQL API with real-time subscriptions, authentication, rate limiting, and comprehensive testing"</p>
<p>Claude's 6-hour autonomous process:</p>
<pre><code class="lang-plaintext">Claude Code &gt; ultrathink: analyzing requirements and designing architecture

[Creates detailed technical specifications and development plan]

Claude Code &gt; implementing core GraphQL server with Apollo
[Runs: npm install apollo-server-express graphql]
[Creates: server.js, schema/typeDefs.js, resolvers/index.js]

Claude Code &gt; adding authentication and authorization middleware
[Creates: middleware/auth.js, utils/jwt.js, models/User.js]
[Implements JWT strategy with proper error handling]

Claude Code &gt; setting up real-time subscriptions with Redis
[Runs: npm install graphql-redis-subscriptions]
[Configures WebSocket connections, creates subscription resolvers]

Claude Code &gt; implementing rate limiting and security measures
[Adds helmet, express-rate-limit, query complexity analysis]

Claude Code &gt; writing comprehensive test suite
[Creates unit tests, integration tests, load tests]
[Runs: npm test - sees 8 failing tests]

Claude Code &gt; fixing test failures automatically
[Identifies async timing issues, fixes resolver logic]
[Re-runs tests repeatedly until 94/94 tests pass]

Claude Code &gt; performance optimization and caching
[Implements Redis caching, optimizes database queries]
[Adds performance monitoring and logging]

Claude Code &gt; generating comprehensive documentation
[Creates API docs with examples, README, deployment guide]

Claude Code &gt; final validation and cleanup
[Runs full test suite, checks code coverage: 96%]
[Creates production build and deployment scripts]
</code></pre>
<p>This represents 6 hours of autonomous work (you can work on other projects while it’s doing this). The result is a production-ready GraphQL API with authentication, real-time features, and comprehensive testing.</p>
<p>Why this works:</p>
<ul>
<li><p><strong>Autonomous Feedback Loops:</strong> Claude runs tests, sees failures, fixes them automatically</p>
</li>
<li><p><strong>Context Awareness:</strong> Maintains understanding of the entire project structure</p>
</li>
<li><p><strong>Self-Correction:</strong> Iterates on solutions until they work properly</p>
</li>
<li><p><strong>Tool Integration:</strong> Uses git, npm, testing frameworks seamlessly</p>
</li>
</ul>
<p><strong>Web Search Integration:</strong></p>
<p>Claude Code can search the web to get current information, which is especially useful since AI training data has cutoff dates. This feature helps you stay current with the latest documentation, best practices, and solutions.</p>
<pre><code class="lang-plaintext">Claude Code &gt; search for the latest React 19 features and update my components

[Claude searches web, then continues the conversation with findings]

Claude Code &gt; now apply those new features to the UserProfile component
</code></pre>
<p><strong>When Web Search Helps:</strong></p>
<ul>
<li><p>Getting current documentation for new library versions</p>
</li>
<li><p>Finding solutions to recent error messages or bugs</p>
</li>
<li><p>Researching latest best practices and patterns</p>
</li>
<li><p>Comparing current approaches to problems</p>
</li>
</ul>
<p>The web search happens automatically when Claude detects it needs current information, or you can explicitly request it by mentioning "search" or "latest" in your prompts.</p>
<h4 id="heading-claude-code-keyboard-shortcuts">Claude Code Keyboard Shortcuts</h4>
<p>You can use these keyboard shortcuts to be even more productive:</p>
<p><strong>Essential controls:</strong></p>
<ul>
<li><p><code>Ctrl+C</code> – Cancel current input or generation</p>
</li>
<li><p><code>Ctrl+D</code> – Exit Claude Code session</p>
</li>
<li><p><code>Ctrl+L</code> – Clear terminal screen</p>
</li>
<li><p><code>Up/Down arrows</code> – Navigate command history</p>
</li>
<li><p><code>Esc</code> + <code>Esc</code> – Edit previous message</p>
</li>
</ul>
<p><strong>Multiline Input:</strong></p>
<ul>
<li><p><code>\</code> + <code>Enter</code> – Quick escape to create newline (works in all terminals)</p>
</li>
<li><p><code>Option+Enter</code> (Mac) / <code>Shift+Enter</code> (configured) – Insert newline</p>
</li>
</ul>
<h3 id="heading-step-12-google-gemini-cli">Step 12: Google Gemini CLI</h3>
<h4 id="heading-when-to-use-gemini-vs-claude-code">When to Use Gemini vs Claude Code:</h4>
<p>Gemini is another CLI-based AI tool that complements Claude Code rather than competing with it. While Claude Code excels at deep reasoning and complex development tasks, Gemini offers unique advantages: massive context windows (1M+ tokens), generous free limits, and powerful multimodal capabilities.</p>
<p><strong>Use Gemini when you:</strong></p>
<ul>
<li><p>Need to analyze entire large codebases at once</p>
</li>
<li><p>Want to process images, diagrams, or sketches</p>
</li>
<li><p>Are working within budget constraints (generous free tier)</p>
</li>
<li><p>Need extremely large context windows for complex projects</p>
</li>
</ul>
<p><strong>Use Claude Code when you:</strong></p>
<ul>
<li><p>Need sophisticated reasoning and problem-solving</p>
</li>
<li><p>Want autonomous development sessions</p>
</li>
<li><p>Prefer advanced thinking modes for complex analysis</p>
</li>
<li><p>Are building production systems requiring detailed planning</p>
</li>
</ul>
<p><strong>The Best Approach:</strong> Many developers use both tools strategically – Gemini for analysis and visual inputs, Claude Code for complex development tasks.</p>
<p>Gemini brings Google's AI to your terminal with generous free limits.</p>
<h4 id="heading-installation-1">Installation</h4>
<p>Using npx (recommended for trying):</p>
<pre><code class="lang-plaintext">npx @google/gemini-cli
</code></pre>
<p>Global installation:</p>
<pre><code class="lang-plaintext">npm install -g @google/gemini-cli
gemini  # Starts interactive session
</code></pre>
<h4 id="heading-authentication">Authentication</h4>
<ol>
<li>Sign in with Google:</li>
</ol>
<pre><code class="lang-plaintext">gemini auth login
</code></pre>
<ol start="2">
<li>Check status:</li>
</ol>
<pre><code class="lang-plaintext">gemini auth status
</code></pre>
<p>Free limits:</p>
<ul>
<li><p>60 requests/minute</p>
</li>
<li><p>1,000 requests/day with Google account</p>
</li>
</ul>
<p>Built-in tools:</p>
<ul>
<li><p><code>/memory</code> – Manage conversation memory</p>
</li>
<li><p><code>/stats</code> – View usage statistics</p>
</li>
<li><p><code>/tools</code> – List available tools</p>
</li>
<li><p><code>/mcp</code> – Configure Model Context Protocol servers</p>
</li>
</ul>
<h4 id="heading-gemini-cli-limitations">Gemini CLI Limitations</h4>
<p>Here are some important considerations if you’re planning to use Gemini:</p>
<ul>
<li><p><strong>Rate limits</strong> – 60 requests/minute and 1,000/day on free tier</p>
</li>
<li><p><strong>Google dependency</strong> – Requires Google account and internet connection</p>
</li>
<li><p><strong>Newer tool</strong> – Smaller community and fewer resources compared to GitHub Copilot</p>
</li>
<li><p><strong>Terminal-focused</strong> – Less integration with popular IDEs</p>
</li>
<li><p><strong>Multimodal processing</strong> – Image uploads have size limits (20MB)</p>
</li>
<li><p><strong>Beta features</strong> – Some advanced features may be unstable</p>
</li>
</ul>
<h4 id="heading-unique-gemini-features">Unique Gemini Features</h4>
<p><strong>Massive Context Window:</strong><br>Gemini can handle 1 million+ tokens in a single session, meaning it can analyze entire large codebases simultaneously. This is particularly useful for understanding complex system architectures and relationships between many files.</p>
<p><strong>Multimodal Capabilities:</strong><br>Gemini can process and understand various types of visual content alongside code, making it uniquely powerful for design-to-code workflows and visual debugging.</p>
<h4 id="heading-turn-your-sketches-into-code">Turn Your Sketches Into Code</h4>
<p>This is really cool: you can literally draw something on paper and Gemini will turn it into working code!</p>
<p>Here's how to do it:</p>
<ol>
<li><p><strong>Create your sketch:</strong> Draw your idea on paper, a whiteboard, or digital tablet</p>
</li>
<li><p><strong>Take a photo or screenshot:</strong> Use your phone or take a screenshot to capture the sketch digitally</p>
</li>
<li><p><strong>Save the image:</strong> Save it as JPG, PNG, or WebP format (under 20MB)</p>
</li>
<li><p><strong>Show it to Gemini using the command line:</strong></p>
</li>
</ol>
<pre><code class="lang-plaintext">gemini -p "Turn this sketch into a React component with nice styling" sketch.jpg
</code></pre>
<p><strong>Alternative methods:</strong></p>
<pre><code class="lang-plaintext"># If you're in an interactive session, you can reference the file:
gemini
&gt; analyze this UI sketch and create the HTML/CSS: @sketch.jpg

# Or drag and drop in supported terminals
gemini
&gt; implement this design as a Vue component
[drag sketch.jpg into terminal]
</code></pre>
<p>Gemini then looks at your drawing and creates:</p>
<ul>
<li><p>A working React component that matches your sketch</p>
</li>
<li><p>Nice CSS styling that makes it look good</p>
</li>
<li><p>Form validation if you drew a form</p>
</li>
<li><p>All the code you need to make it work</p>
</li>
</ul>
<p>It's like having a designer and developer that can read your mind!</p>
<h4 id="heading-fix-bugs-by-showing-gemini-images">Fix Bugs By Showing Gemini Images</h4>
<p>Got a bug in your UI? You can show Gemini visual information to help debug:</p>
<pre><code class="lang-plaintext">gemini -p "This UI looks broken. What's wrong and how do I fix it?" image.png
</code></pre>
<p>Gemini can analyze visual information and tell you:</p>
<ul>
<li><p>What's causing the problem</p>
</li>
<li><p>Exactly what code to change</p>
</li>
<li><p>Sometimes even better ways to do it</p>
</li>
</ul>
<h4 id="heading-turn-architecture-diagrams-into-code">Turn Architecture Diagrams Into Code</h4>
<p>Draw a system diagram and Gemini can build it:</p>
<pre><code class="lang-plaintext">gemini -p "Build this system architecture with Docker and databases" diagram.jpg
</code></pre>
<p>Gemini will:</p>
<ul>
<li><p>Understand your diagram</p>
</li>
<li><p>Create all the Docker files you need</p>
</li>
<li><p>Set up the databases and connections</p>
</li>
<li><p>Give you a working system based on your design</p>
</li>
</ul>
<h4 id="heading-why-this-visual-coding-is-amazing">Why This Visual Coding is Amazing</h4>
<p>Instead of spending hours translating a design into code, you can:</p>
<ol>
<li><p>Show Gemini your sketch or design</p>
</li>
<li><p>Ask Gemini to build it</p>
</li>
<li><p>Get working code in minutes instead of hours and just refine as necessary</p>
</li>
</ol>
<p>Most of the time, Gemini gets pretty close to what you wanted on the first try. Even when it's not perfect, it gives you a great starting point that saves you tons of time.</p>
<h3 id="heading-step-13-comparing-cli-tools">Step 13: Comparing CLI Tools</h3>
<p>Here’s a quick table to help you compare the features of Claude Code and Gemini CLI:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Claude Code</strong></td><td><strong>Gemini CLI</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Context Window</strong></td><td>Large</td><td>1M+ tokens</td></tr>
<tr>
<td><strong>Web Search</strong></td><td>Built-in</td><td>Google Search integration</td></tr>
<tr>
<td><strong>File Editing</strong></td><td>Direct edits</td><td>Diff-based</td></tr>
<tr>
<td><strong>Thinking Modes</strong></td><td>4 levels</td><td>ReAct loop</td></tr>
<tr>
<td><strong>IDE Integration</strong></td><td>VS Code shortcuts</td><td>Terminal-first</td></tr>
<tr>
<td><strong>Free Tier</strong></td><td>Limited</td><td>Generous (1000/day)</td></tr>
<tr>
<td><strong>Open Source</strong></td><td>No</td><td>Yes</td></tr>
<tr>
<td><strong>Multimodal</strong></td><td>No</td><td>Yes (images, PDFs)</td></tr>
</tbody>
</table>
</div><h3 id="heading-step-14-advanced-cli-workflows">Step 14: Advanced CLI Workflows</h3>
<h4 id="heading-workflow-1-interactive-code-review-with-claude-code">Workflow 1: Interactive Code Review with Claude Code</h4>
<pre><code class="lang-plaintext">Claude Code &gt; review my recent git changes

[Claude analyzes the diff]

Claude Code &gt; fix the security issue you found in the login function

Claude Code &gt; now create a pull request with a good description
</code></pre>
<h4 id="heading-workflow-2-conversational-architecture-analysis-with-gemini">Workflow 2: Conversational Architecture Analysis with Gemini</h4>
<pre><code class="lang-plaintext">Gemini &gt; analyze this codebase architecture and identify technical debt

[Gemini provides comprehensive analysis]

Gemini &gt; create a migration plan for the database issues you found

Gemini &gt; generate API documentation for the endpoints
</code></pre>
<h4 id="heading-workflow-3-interactive-test-driven-development">Workflow 3: Interactive Test-Driven Development</h4>
<pre><code class="lang-plaintext">Claude Code &gt; I need to add payment processing. Start by writing comprehensive tests

[Claude creates test suite]

Claude Code &gt; now implement the payment service to pass these tests

Claude Code &gt; add error handling and edge cases
</code></pre>
<h3 id="heading-combining-vs-code-with-cli-tools">Combining VS Code with CLI Tools</h3>
<h4 id="heading-the-power-of-hybrid-workflows">The Power of Hybrid Workflows:</h4>
<p>The most productive developers don't typically choose just one AI tool – they strategically combine VS Code extensions with CLI tools to maximize their efficiency. Each tool has unique strengths, and combining them creates a workflow that's greater than the sum of its parts.</p>
<p><strong>Benefits of Combining Tools:</strong></p>
<ul>
<li><p><strong>Seamless Context Switching:</strong> Start with Copilot for rapid development, then seamlessly move to Claude Code for complex analysis without losing momentum</p>
</li>
<li><p><strong>Complementary Strengths:</strong> Use each tool's best features, like Copilot's real-time suggestions + Claude's deep reasoning + Gemini's visual processing</p>
</li>
<li><p><strong>Continuous Workflow:</strong> No need to copy/paste code between tools - work directly in your project with different AI assistance as needed</p>
</li>
<li><p><strong>Reduced Mental Load:</strong> Tools handle different cognitive tasks, letting you focus on creative problem-solving</p>
</li>
</ul>
<h4 id="heading-how-to-practically-combine-tools">How to Practically Combine Tools:</h4>
<p>Example workflow – building a user dashboard:</p>
<ol>
<li><p><strong>Start in VS Code with Copilot:</strong> Use tab completion to rapidly build basic component structure</p>
</li>
<li><p><strong>Keep VS Code open, launch Claude Code:</strong> Get architectural advice and refactoring suggestions while maintaining your editor context</p>
</li>
<li><p><strong>Switch to Gemini for visual elements:</strong> Upload UI mockups to generate matching styles</p>
</li>
<li><p><strong>Return to VS Code:</strong> Apply all suggestions with Copilot helping with implementation details</p>
</li>
</ol>
<p><strong>Key Integration Points:</strong></p>
<ul>
<li><p><strong>Shared Project Context:</strong> All tools work in the same directory, understanding your project structure</p>
</li>
<li><p><strong>File System Coordination:</strong> Changes made by CLI tools are immediately visible in VS Code</p>
</li>
<li><p><strong>Version Control Integration:</strong> Use CLI tools for git operations while VS Code shows visual diffs</p>
</li>
</ul>
<h3 id="heading-quick-switching-setup">Quick Switching Setup</h3>
<h4 id="heading-what-is-quick-switching">What is Quick Switching?</h4>
<p>A quick switching setup refers to configuring your development environment so you can rapidly move between different AI tools without friction. Instead of typing long commands or navigating through multiple setup steps, you create shortcuts that let you instantly access the right AI tool for your current task.</p>
<p>Add to your shell config (<code>.zshrc</code> or <code>.bashrc</code>):</p>
<pre><code class="lang-plaintext"># Quick AI commands for interactive mode
alias cc="claude"
alias gc="gemini"

# For quick one-shot commands when needed
alias think="claude 'think hard:'"
alias analyze="gemini -p 'analyze:'"
</code></pre>
<h3 id="heading-stage-3-practice-exercises">Stage 3 Practice Exercises</h3>
<h4 id="heading-exercise-1-interactive-claude-code-project-setup">Exercise 1: Interactive Claude Code Project Setup</h4>
<ol>
<li><p>Create a new project directory</p>
</li>
<li><p>Launch: <code>claude</code></p>
</li>
<li><p>Start conversation: "set up a Node.js Express API with PostgreSQL"</p>
</li>
<li><p>Continue chatting: "add authentication middleware"</p>
</li>
<li><p>Keep going: "now add comprehensive error handling"</p>
</li>
<li><p>Review the generated code and ask questions</p>
</li>
</ol>
<h4 id="heading-exercise-2-interactive-gemini-codebase-analysis">Exercise 2: Interactive Gemini Codebase Analysis</h4>
<ol>
<li><p>Navigate to an existing project</p>
</li>
<li><p>Launch: <code>gemini</code></p>
</li>
<li><p>Start with: "analyze this codebase and identify potential security vulnerabilities"</p>
</li>
<li><p>Follow up: "explain the most critical issue in detail"</p>
</li>
<li><p>Continue: "create a fix for the authentication vulnerability"</p>
</li>
<li><p>Ask: "what other improvements should I prioritize?"</p>
</li>
</ol>
<h4 id="heading-exercise-3-interactive-combined-workflow">Exercise 3: Interactive Combined Workflow</h4>
<ol>
<li><p>Start with Copilot in VS Code for initial development</p>
</li>
<li><p>Switch to interactive Claude Code session for complex refactoring</p>
</li>
<li><p>Use interactive Gemini session for codebase analysis and documentation</p>
</li>
<li><p>Practice seamlessly moving between tools</p>
</li>
</ol>
<p>Need help with CLI tools? See the <a class="post-section-overview" href="#heading-troubleshooting-quick-reference">Troubleshooting Quick Reference</a> for setup and common issues.</p>
<h2 id="heading-stage-4-mastery-combining-tools-and-advanced-workflows">Stage 4: Mastery – Combining Tools and Advanced Workflows</h2>
<h3 id="heading-step-15-tool-selection-strategy">Step 15: Tool Selection Strategy</h3>
<h4 id="heading-when-to-use-each-tool">When to Use Each Tool</h4>
<p>Alright, so when should you use each tool in your workflows?</p>
<p>You can use GitHub Copilot as an inline pair-programmer when speed matters. It helps you crank out new functions, get real-time suggestions as you type, and pick up unfamiliar APIs or frameworks on the fly. It’s also handy for quick docs lookups without breaking your flow.</p>
<p>Then you can switch to Claude Code for bigger, messier jobs: complex multi-file refactors, drafting comprehensive tests, and “thinking out loud” about architecture and trade-offs. Here it also helps with Git tasks like guiding you through operations and assembling pull requests.</p>
<p>Finally, you can reach for the Gemini CLI from the terminal when you need to analyze large codebases end-to-end or incorporate visual inputs (like screenshots/diagrams) into your workflow. It’s useful for lots of runs thanks to a free tier, and it fits scenarios where you might want a customizable, script-friendly setup.</p>
<h3 id="heading-step-16-understanding-mcp-making-ai-tools-work-together">Step 16: Understanding MCP – Making AI Tools Work Together</h3>
<h4 id="heading-what-is-mcp">What is MCP?</h4>
<p>MCP (Model Context Protocol) is a simple way to give your AI tools extra powers. Think of it like adding apps to your phone – each MCP server adds a new capability to your AI.</p>
<h4 id="heading-why-should-beginners-care-about-mcp">Why Should Beginners Care About MCP?</h4>
<p>Here’s the problem without MCP: your AI can only work with what it knows and what you tell it. It can't:</p>
<ul>
<li><p>Search the web for current information</p>
</li>
<li><p>Test your website automatically</p>
</li>
<li><p>Remember your project details between sessions</p>
</li>
<li><p>Connect to your databases or APIs</p>
</li>
</ul>
<p>But with MCP servers, your AI can suddenly:</p>
<ul>
<li><p><strong>Get current information</strong> – Search Google for latest docs and solutions</p>
</li>
<li><p><strong>Test your code</strong> – Automatically check if your website works</p>
</li>
<li><p><strong>Remember your project</strong> – Keep track of your architecture and decisions</p>
</li>
<li><p><strong>Connect to tools</strong> – Work with GitHub, databases, and more</p>
</li>
</ul>
<p>So instead of manually doing repetitive tasks, your AI can handle them automatically. This means you’ll spend less time googling error messages, manually testing your code, and explaining your project to the AI each session. And you’ll spend more time actually building things.</p>
<h4 id="heading-simple-mcp-examples-for-beginners">Simple MCP Examples for Beginners</h4>
<p>Here are beginner-friendly examples of what MCP can do for you:</p>
<p><strong>Example 1: Getting Help Without Googling</strong></p>
<pre><code class="lang-plaintext">You: "This CSS isn't working. Find out why and fix it"

Without MCP: You'd google the error, read docs, try solutions
With MCP: AI searches current CSS docs, finds the issue, fixes it automatically
</code></pre>
<p><strong>Example 2: Testing Your Website Automatically</strong></p>
<pre><code class="lang-plaintext">You: "Check if my contact form actually works"

Without MCP: You'd manually fill out the form, check email, test edge cases
With MCP: AI fills out the form, verifies email is sent, tests different inputs
</code></pre>
<p><strong>Example 3: AI Remembers Your Project</strong></p>
<pre><code class="lang-plaintext">You: "Add a new feature to my todo app"

Without MCP: You explain your database structure, API routes, frontend framework
With MCP: AI already remembers everything and just builds the feature
</code></pre>
<h4 id="heading-ready-to-try-mcp">Ready to Try MCP?</h4>
<p>Don't worry if this seems overwhelming! You can start with just one simple MCP server and add more as you get comfortable.</p>
<h4 id="heading-easy-mcp-setup-for-beginners">Easy MCP Setup for Beginners</h4>
<p>We’ll start with VS Code (as it’s the easiest option):</p>
<ol>
<li><p>Open VS Code</p>
</li>
<li><p>Go to Extensions (Ctrl+Shift+X)</p>
</li>
<li><p>Search for "GitHub Copilot MCP" or similar MCP extensions</p>
</li>
<li><p>Click "Install"</p>
</li>
</ol>
<p>And you’re done! The extension handles everything automatically</p>
<p>With this, you get web search capability for your AI, basic project memory, and simple automation features.</p>
<p>To test it out, ask your AI: "Search for the latest React best practices and show me an example". If it can search and bring back current information, MCP is working!</p>
<h4 id="heading-want-more-mcp-power">Want More MCP Power?</h4>
<p>Once you're comfortable with basic MCP, you can explore a more advanced setup below:</p>
<ul>
<li><p>Custom MCP server installation</p>
</li>
<li><p>Advanced configuration options</p>
</li>
<li><p>Building your own MCP integrations</p>
</li>
</ul>
<p>For now, the VS Code extension approach above will give you plenty of AI superpowers to get started!</p>
<p><strong>That's MCP in a nutshell!</strong> Start with the simple VS Code extension approach above, and you'll quickly see how much more powerful your AI becomes.</p>
<h4 id="heading-next-steps">Next Steps</h4>
<ul>
<li><p>Try the basic VS Code MCP extension</p>
</li>
<li><p>Test it with simple requests like "search for X and implement it"</p>
</li>
<li><p>Once comfortable, explore more MCP servers in Stage 4</p>
</li>
</ul>
<p>MCP transforms your AI from a code suggester into a true development partner. The best part? Once you set it up with one tool, it works with all of them!</p>
<h4 id="heading-mcp-not-working">MCP Not Working?</h4>
<p>If the AI says it can't search the web, there are a couple things you can try.</p>
<p>First, check if the MCP extension is actually installed in VS Code. Then try restarting VS Code. Finally, make sure you're asking in a way the AI understands: "Search for X and show me Y".</p>
<p>If VS Code extension won't install, try checking your internet connection or updating VS Code to the latest version. You can also look for "MCP" or "Model Context Protocol" extensions in different names.</p>
<p>If you’re still having trouble, we’ll cover advanced troubleshooting below. Or you can also ask your AI: "Help me troubleshoot MCP setup".</p>
<h3 id="heading-advanced-mcp-setup-and-integration">Advanced MCP Setup and Integration</h3>
<h4 id="heading-manual-mcp-server-installation">Manual MCP Server Installation</h4>
<p>For advanced users who want full control over their MCP setup:</p>
<p><strong>Step 1: Install MCP Servers</strong></p>
<p>Most MCP servers can be installed via npm:</p>
<pre><code class="lang-plaintext"># For web automation and testing
npm install -g @modelcontextprotocol/server-puppeteer

# For web search without API keys
npm install -g @mcp-servers/duckduckgo

# For database access
npm install -g @modelcontextprotocol/server-postgres
</code></pre>
<p>Some servers (like GitHub) use Docker instead:</p>
<pre><code class="lang-plaintext">docker pull ghcr.io/github/github-mcp-server
</code></pre>
<p><strong>Step 2: Configure Your Tool</strong></p>
<p><strong>Understanding Hierarchical Configuration:</strong></p>
<p>Each AI tool checks for MCP configurations in multiple locations, prioritizing more specific settings over general ones. This means you can have global defaults but override them for specific projects. Think of it like CSS – more specific rules override general ones.</p>
<p><strong>Claude Code has the most flexible setup:</strong></p>
<p>Claude Code configuration hierarchy (checked in order):</p>
<ol>
<li><p><strong>Project level</strong>: <code>.claude/mcp.json</code> (highest priority)</p>
</li>
<li><p><strong>Local settings</strong>: <code>.claude/settings.local.json</code></p>
</li>
<li><p><strong>Global config</strong>: <code>~/.claude/mcp.json</code> (fallback)</p>
</li>
</ol>
<p>Other tools:</p>
<ul>
<li><p><strong>VS Code</strong>: <code>.vscode/mcp.json</code> (project-level only)</p>
</li>
<li><p><strong>Cursor</strong>: <code>.cursor/mcp.json</code> (project-level only)</p>
</li>
<li><p><strong>Windsurf</strong>: Uses VS Code's configuration format</p>
</li>
</ul>
<p>Here’s an example configuration (works in any tool, just adjust the file location):</p>
<pre><code class="lang-plaintext">{
  "mcpServers": {
    "puppeteer": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-puppeteer"]
    },
    "duckduckgo": {
      "command": "npx",
      "args": ["@mcp-servers/duckduckgo"]
    },
    "github": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your_token_here"
      }
    }
  }
}
</code></pre>
<h4 id="heading-production-mcp-servers">Production MCP Servers</h4>
<p><strong>1. Game-Changing Cognitive Tools:</strong></p>
<p><strong>Sequential Thinking Server:</strong><br>This server transforms how AI approaches complex problems by breaking them into logical steps. When you ask for a large feature implementation, instead of jumping straight to code, the AI first creates a detailed plan with phases, dependencies, and decision points.</p>
<p>This is invaluable for refactoring legacy systems or building new features where order of operations matters. The server maintains this planning context throughout the entire development session, ensuring consistent decision-making.</p>
<p><strong>Memory Bank Server:</strong><br>Eliminates the frustrating need to re-explain your project structure every session. This server creates persistent memory about your architecture choices, coding standards, team preferences, and project goals. When you return to work days later, the AI immediately knows your database schema, API patterns, and even why certain decisions were made. It's like having a project documentation system that stays perfectly synchronized with your development work.</p>
<p><strong>Knowledge Graph Server:</strong><br>Creates a living map of your codebase relationships – not just file dependencies, but conceptual connections between features, shared utilities, and architectural patterns. When you modify one component, the AI can instantly identify all related areas that might need updates. This prevents bugs caused by missing related changes and helps with impact analysis during refactoring.</p>
<p><strong>2. Web Automation &amp; Testing Servers:</strong></p>
<p><strong>Puppeteer Server:</strong><br>Provides headless Chrome browser control for comprehensive testing workflows. The AI can automatically navigate your web application, fill forms, click buttons, and verify expected behaviors.</p>
<p>This is particularly powerful for regression testing – the AI can replay user workflows and catch breaking changes before deployment. It also enables screenshot-based testing and performance monitoring automation.</p>
<p><strong>Playwright Server:</strong><br>Extends browser automation across Chrome, Firefox, and Safari simultaneously. This server is essential for cross-browser compatibility testing and allows the AI to catch browser-specific issues early in development.</p>
<p>Unlike manual testing, the AI can run identical test scenarios across all browsers in parallel, generating comparative reports on functionality and performance differences.</p>
<p><strong>3. Development Integration Servers:</strong></p>
<p><strong>GitHub Server:</strong><br>Transforms your terminal into a full GitHub interface with AI intelligence. The AI can automatically create branches, manage pull requests, analyze code review comments, and even generate PR descriptions based on code changes. It can also triage issues, assign labels based on content analysis, and maintain project boards by understanding the relationship between issues and actual code changes.</p>
<p><strong>DuckDuckGo Search Server:</strong><br>Provides real-time access to current documentation and solutions without API costs. When the AI encounters errors or needs to verify best practices, it can instantly search for the most recent information. This is crucial for rapidly evolving technologies where training data becomes outdated quickly. The server also helps with troubleshooting by finding solutions to error messages you haven't seen before.</p>
<p><strong>PostgreSQL Server:</strong><br>Enables direct database analysis and optimization. The AI can examine query performance, suggest index optimizations, analyze data patterns, and even generate migration scripts. This server is particularly valuable for debugging production issues where the AI needs to understand actual data distribution and query execution patterns rather than just theoretical database design.</p>
<p><strong>4. Helper Tools:</strong></p>
<p><strong>MCP Compass</strong><br>Helps you find the right MCP server for any task.</p>
<p>These servers turn your AI from a code suggester into a real development partner that can test, search, remember, and automate!</p>
<h3 id="heading-step-17-advanced-prompt-engineering">Step 17: Advanced Prompt Engineering</h3>
<h4 id="heading-contextual-prompting">Contextual Prompting</h4>
<p>Provide examples:</p>
<pre><code class="lang-plaintext">// Instead of: "create a validation function"
// Use: "create a validation function like this one but for email:
// function validatePhone(phone) { return /^\d{10}$/.test(phone); }"
</code></pre>
<p>Specify constraints:</p>
<pre><code class="lang-plaintext">claude "refactor this code to use functional programming, no loops, use map/filter/reduce"
</code></pre>
<p>Include edge cases:</p>
<pre><code class="lang-plaintext">gemini -p "implement user authentication that handles: expired tokens, concurrent logins, rate limiting"
</code></pre>
<h3 id="heading-step-18-building-ai-assisted-development-pipelines">Step 18: Building AI-Assisted Development Pipelines</h3>
<h4 id="heading-automated-code-review-pipeline">Automated Code Review Pipeline</h4>
<ol>
<li>Pre-commit with Copilot:</li>
</ol>
<pre><code class="lang-plaintext">// .copilot-instructions
"Review all changes for: security issues, performance problems, code style";
</code></pre>
<ol start="2">
<li>PR Review with Claude:</li>
</ol>
<pre><code class="lang-plaintext">claude "review this PR: git diff main..feature-branch"
</code></pre>
<ol start="3">
<li>Documentation with Gemini:</li>
</ol>
<pre><code class="lang-plaintext">gemini -p "generate changelog and update README for these changes"
</code></pre>
<h4 id="heading-test-driven-ai-development">Test-Driven AI Development</h4>
<ol>
<li>Write test specifications:</li>
</ol>
<pre><code class="lang-plaintext">claude "write comprehensive test specs for a payment processing system"
</code></pre>
<ol start="2">
<li>Generate test code:</li>
</ol>
<pre><code class="lang-plaintext">gemini -p "implement these test specifications using Jest"
</code></pre>
<ol start="3">
<li><p>Implement with Copilot:</p>
<ul>
<li><p>Use Agent Mode to implement features</p>
</li>
<li><p>Tests guide the implementation</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-step-19-creating-your-personal-ai-workflow">Step 19: Creating Your Personal AI Workflow</h3>
<h4 id="heading-setting-up-your-environment">Setting Up Your Environment</h4>
<p>1. VS Code Settings (<code>settings.json</code>):</p>
<pre><code class="lang-plaintext">{
  "github.copilot.enable": {
    "*": true
  },
  "github.copilot.advanced": {
    "inlineCompletions.enable": true,
    "chat.enabled": true
  }
}
</code></pre>
<p>2. Claude Code Configuration (<code>~/.claude/settings.json</code>):</p>
<pre><code class="lang-plaintext">{
  "cleanupPeriodDays": 7,
  "permissions": {
    "allow": [
      "Bash(fd:*)",
      "Bash(rg:*)",
      "Bash(ls:*)",
      "WebFetch(domain:github.com)",
      "WebFetch(domain:stackoverflow.com)"
    ],
    "deny": ["WebFetch(domain:medium.com)"]
  }
}
</code></pre>
<p>3. Gemini Setup (<code>~/.gemini/config.json</code>):</p>
<pre><code class="lang-plaintext">{
  "defaultModel": "gemini-2.5-pro",
  "contextWindow": "large",
  "safetyMode": "interactive"
}
</code></pre>
<h4 id="heading-custom-commands-and-aliases">Custom Commands and Aliases</h4>
<p>Shell aliases for common tasks:</p>
<pre><code class="lang-plaintext"># Launch interactive sessions
alias cc='claude'
alias gc='gemini'

# Quick one-shot commands (when you need them)
alias aicommit='claude "create a git commit with a descriptive message"'
alias aireview='claude "review my uncommitted changes"'
alias complexity='gemini -p "analyze code complexity and suggest simplifications"'
alias security='claude "think harder: check for security vulnerabilities"'
alias aidocs='gemini -p "generate comprehensive documentation"'
</code></pre>
<h3 id="heading-final-project-build-a-full-application-with-ai">Final Project: Build a Full Application with AI</h3>
<h4 id="heading-project-requirements">Project Requirements</h4>
<p>Build a task management API with:</p>
<ul>
<li><p>User authentication</p>
</li>
<li><p>CRUD operations</p>
</li>
<li><p>Real-time updates</p>
</li>
<li><p>Testing suite</p>
</li>
<li><p>Documentation</p>
</li>
</ul>
<h4 id="heading-suggested-workflow">Suggested Workflow</h4>
<p>Phase 1: Interactive Planning</p>
<pre><code class="lang-plaintext"># Start Claude Code session
claude

Claude Code &gt; ultrathink: design a scalable task management API architecture

[Claude provides detailed analysis]

Claude Code &gt; now break this down into implementation phases

# Switch to Gemini for specifications
gemini

Gemini &gt; create detailed technical specifications for this task management API

Gemini &gt; include database schema and API endpoint specifications
</code></pre>
<p>Phase 2: Interactive Implementation</p>
<ol>
<li><p>Use Copilot Agent Mode for initial setup</p>
</li>
<li><p>Implement features with inline Copilot</p>
</li>
<li><p>Switch to interactive Claude Code session for complex logic:</p>
</li>
</ol>
<pre><code class="lang-plaintext">Claude Code &gt; implement the user authentication system we planned

Claude Code &gt; now add the task CRUD operations

Claude Code &gt; integrate real-time updates with WebSockets
</code></pre>
<p>Phase 3: Interactive Testing &amp; Documentation</p>
<pre><code class="lang-plaintext"># Claude Code session for testing
claude

Claude Code &gt; write comprehensive tests for all API endpoints

Claude Code &gt; add integration tests for the authentication flow

Claude Code &gt; create performance tests for high load scenarios

# Gemini session for documentation
gemini

Gemini &gt; generate comprehensive API documentation with examples

Gemini &gt; create a developer onboarding guide
</code></pre>
<p>Phase 4: Interactive Optimization</p>
<pre><code class="lang-plaintext"># Claude Code for performance optimization
claude

Claude Code &gt; analyze and optimize our database queries

Claude Code &gt; implement caching for frequently accessed data

Claude Code &gt; add monitoring and logging

# Gemini for final review
gemini

Gemini &gt; review the entire codebase for improvements

Gemini &gt; identify potential security vulnerabilities

Gemini &gt; suggest deployment optimizations
</code></pre>
<h3 id="heading-measuring-your-progress">Measuring Your Progress</h3>
<h4 id="heading-stage-1-milestones">Stage 1 Milestones</h4>
<ul>
<li><p>Comfortable with tab completion</p>
</li>
<li><p>Can write effective prompts</p>
</li>
<li><p>Understand AI limitations</p>
</li>
</ul>
<h4 id="heading-stage-2-milestones">Stage 2 Milestones</h4>
<ul>
<li><p>Using multiple models effectively</p>
</li>
<li><p>Mastering chat modes and agents</p>
</li>
<li><p>Using advanced chat features</p>
</li>
</ul>
<h4 id="heading-stage-3-milestones">Stage 3 Milestones</h4>
<ul>
<li><p>Fluent with CLI tools</p>
</li>
<li><p>Can combine VS Code and terminal workflows</p>
</li>
<li><p>Understanding tool strengths</p>
</li>
</ul>
<h4 id="heading-stage-4-milestones">Stage 4 Milestones</h4>
<ul>
<li><p>Created custom AI workflow</p>
</li>
<li><p>Built complete application with AI</p>
</li>
<li><p>Can teach others AI-assisted development</p>
</li>
</ul>
<h3 id="heading-stage-4-practice-exercises">Stage 4 Practice Exercises</h3>
<h4 id="heading-exercise-1-tool-selection-mastery">Exercise 1: Tool Selection Mastery</h4>
<ol>
<li><p>Pick a medium-complexity coding task (for example, "Build a URL shortener API")</p>
</li>
<li><p>Plan which tool to use for each phase (design, coding, testing, deployment)</p>
</li>
<li><p>Execute using your chosen workflow</p>
</li>
<li><p>Document what worked well and what you'd change</p>
</li>
</ol>
<h4 id="heading-exercise-2-custom-workflow-creation">Exercise 2: Custom Workflow Creation</h4>
<ol>
<li><p>Identify a repetitive development task in your work</p>
</li>
<li><p>Design an AI-assisted workflow using multiple tools</p>
</li>
<li><p>Test and refine the workflow</p>
</li>
<li><p>Create documentation for teammates</p>
</li>
</ol>
<h4 id="heading-exercise-3-complete-project-build">Exercise 3: Complete Project Build</h4>
<ol>
<li><p>Build a small but complete application using only AI assistance</p>
</li>
<li><p>Use at least 2 different AI tools strategically</p>
</li>
<li><p>Include testing, documentation, and deployment</p>
</li>
<li><p>Reflect on productivity gains vs traditional development</p>
</li>
</ol>
<h3 id="heading-continuing-your-journey">Continuing Your Journey</h3>
<h4 id="heading-stay-updated">Stay Updated</h4>
<ul>
<li><p>Follow tool release notes</p>
</li>
<li><p>Join AI coding communities</p>
</li>
<li><p>Experiment with new features</p>
</li>
</ul>
<h4 id="heading-advanced-topics-to-explore">Advanced Topics to Explore</h4>
<ul>
<li><p>Custom MCP server development</p>
</li>
<li><p>AI model fine-tuning</p>
</li>
<li><p>Enterprise deployment strategies</p>
</li>
<li><p>Team collaboration patterns</p>
</li>
</ul>
<h4 id="heading-resources-for-continued-learning">Resources for Continued Learning</h4>
<ul>
<li><p>Official documentation for each tool</p>
</li>
<li><p>Community forums and Discord servers</p>
</li>
<li><p>Open-source AI coding projects</p>
</li>
<li><p>Conference talks and tutorials</p>
</li>
</ul>
<h2 id="heading-common-ai-issues">Common AI Issues</h2>
<p>Even with the best AI tools, you'll encounter challenges. These issues are normal and manageable once you understand their patterns. Here are the most common problems developers face and practical solutions that actually work.</p>
<h3 id="heading-my-ai-suggestions-are-terrible">"My AI suggestions are terrible!"</h3>
<p><strong>Problem:</strong> AI gives irrelevant or wrong suggestions</p>
<p><strong>Solution:</strong></p>
<ul>
<li><p>Write clearer comments</p>
</li>
<li><p>Open related files for context</p>
</li>
<li><p>Start with simpler tasks</p>
</li>
<li><p>Make sure you're in the right file type</p>
</li>
</ul>
<p><strong>Example Fix:</strong></p>
<pre><code class="lang-plaintext">// Instead of: "make function"
// Try: "create function to validate US phone number format (xxx) xxx-xxxx"
</code></pre>
<h3 id="heading-ai-is-too-slow">"AI is too slow"</h3>
<p><strong>Problem:</strong> Waiting too long for suggestions</p>
<p><strong>Solution:</strong></p>
<ul>
<li><p>Check your internet connection</p>
</li>
<li><p>Close unnecessary programs</p>
</li>
<li><p>Try a lighter-weight AI tool</p>
</li>
<li><p>Be patient - complex suggestions take time</p>
</li>
</ul>
<h3 id="heading-im-afraid-of-becoming-dependent-on-ai">"I'm afraid of becoming dependent on AI"</h3>
<p><strong>Problem:</strong> Worried about losing coding skills</p>
<p><strong>Solution:</strong></p>
<ul>
<li><p>Use AI as a learning tool, not a crutch</p>
</li>
<li><p>Always understand the code before accepting</p>
</li>
<li><p>Practice coding without AI regularly</p>
</li>
<li><p>Focus on problem-solving, not syntax</p>
</li>
</ul>
<h3 id="heading-its-suggesting-outdated-code">"It's suggesting outdated code"</h3>
<p><strong>Problem:</strong> AI suggests old patterns or deprecated methods</p>
<p><strong>Solution:</strong></p>
<ul>
<li><p>Specify versions in your comments</p>
</li>
<li><p>Keep your tools updated</p>
</li>
<li><p>Learn to recognize outdated patterns</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-plaintext">// create React functional component using hooks (not class component)
</code></pre>
<h3 id="heading-troubleshooting-quick-reference">Troubleshooting Quick Reference</h3>
<h4 id="heading-common-issues-all-tools">Common Issues (All Tools)</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Problem</strong></td><td><strong>Quick Fix</strong></td></tr>
</thead>
<tbody>
<tr>
<td>No AI suggestions</td><td>Check internet connection, restart editor, verify login</td></tr>
<tr>
<td>"Need to pay" message</td><td>Check free tier limits, verify account status</td></tr>
<tr>
<td>Suggestions are poor</td><td>Use clearer comments, open related files for context</td></tr>
<tr>
<td>Tool won't install</td><td>Update editor, check internet, try different installation method</td></tr>
</tbody>
</table>
</div><h4 id="heading-github-copilot-issues">GitHub Copilot Issues</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Problem</strong></td><td><strong>Solution</strong></td></tr>
</thead>
<tbody>
<tr>
<td>No suggestions in VS Code</td><td>Check bottom-right for "GitHub Copilot" status</td></tr>
<tr>
<td>Free tier expired</td><td>Check <a target="_blank" href="https://docs.github.com/en/copilot/how-tos/manage-your-account/getting-free-access-to-copilot-pro-as-a-student-teacher-or-maintainer">free access for students/maintainers</a></td></tr>
<tr>
<td>Agent Mode not working</td><td>Try <code>Shift+Cmd+I</code> (Mac) or <code>Ctrl+Shift+I</code> (Windows/Linux)</td></tr>
<tr>
<td>Chat not responding</td><td>Try restarting VS Code, check internet connection</td></tr>
</tbody>
</table>
</div><h4 id="heading-claude-code-issues">Claude Code Issues</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Problem</strong></td><td><strong>Solution</strong></td></tr>
</thead>
<tbody>
<tr>
<td>"Command not found"</td><td>Reinstall: <code>npm uninstall -g @anthropic-ai/claude-code &amp;&amp; npm install -g @anthropic-ai/claude-code</code></td></tr>
<tr>
<td>Authentication failed</td><td>Run <code>claude auth login</code>, check API credits remaining</td></tr>
<tr>
<td>Slow responses</td><td>Check network: <code>ping api.anthropic.com</code>, try lighter model with <code>--model claude-3-haiku</code></td></tr>
<tr>
<td>MCP servers not working</td><td>Check <code>~/.claude/mcp.json</code> syntax, test server: <code>npx @mcp/server-github --help</code></td></tr>
<tr>
<td>Commands hang/freeze</td><td>Press <code>Ctrl+C</code> to cancel, restart terminal, check background processes</td></tr>
</tbody>
</table>
</div><h4 id="heading-gemini-cli-issues">Gemini CLI Issues</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Problem</strong></td><td><strong>Solution</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Authentication required</td><td>Run <code>gemini auth login</code>, check Google account permissions</td></tr>
<tr>
<td>Rate limit exceeded</td><td>Check usage: <code>gemini /stats</code>, wait 1 minute or upgrade plan</td></tr>
<tr>
<td>Won't install</td><td>Try <code>npx @google/gemini-cli</code> instead, check Node.js 16+</td></tr>
<tr>
<td>Image upload fails</td><td>Check format (JPG/PNG/WebP), size under 20MB, verify file path</td></tr>
<tr>
<td>Context window errors</td><td>Break large requests into smaller chunks, clear history</td></tr>
</tbody>
</table>
</div><h3 id="heading-emergency-checklist">Emergency Checklist</h3>
<p>When nothing works, try these in order:</p>
<ol>
<li><p>Restart your editor/terminal</p>
</li>
<li><p>Check internet connection</p>
</li>
<li><p>Verify you're logged in to the right account</p>
</li>
<li><p>Update to latest version of the tool</p>
</li>
<li><p>Try a different tool (if one fails, others usually work)</p>
</li>
<li><p>Ask the AI itself: "Help me troubleshoottool<em>tool</em>setup"</p>
</li>
</ol>
<h2 id="heading-whats-next-after-completing-all-stages">What's Next After Completing All Stages?</h2>
<p>Once you've mastered the basics, here are some simple next steps:</p>
<h3 id="heading-working-with-your-team">Working with Your Team</h3>
<h4 id="heading-team-ai-workflow-basics">Team AI Workflow Basics</h4>
<p><strong>Shared Prompt Libraries:</strong></p>
<p>Building a team prompt library transforms how your entire team uses AI. Start by creating a shared repository where developers document prompts that work well for your specific domain and codebase.</p>
<p>For example, if you're building e-commerce software, create standardized prompts for common tasks like "generate product catalog API endpoints following our REST conventions" or "create payment processing error handling using our standard patterns."</p>
<p>Document successful Agent Mode workflows that team members can reuse. One developer might discover that Claude Code works particularly well for database migrations when given specific context about your schema evolution practices. By sharing these workflows, you prevent each team member from having to discover effective approaches independently.</p>
<p><strong>Tool Standardization:</strong></p>
<p>Team productivity multiplies when everyone uses compatible AI tools. Agree on primary tools based on your team's needs - for instance, GitHub Copilot for all developers to ensure consistent inline assistance, plus Claude Code for complex architectural tasks that benefit from deep reasoning. Establish clear guidelines about when to use autonomous Agent Mode versus collaborative sessions to prevent conflicts and ensure code quality.</p>
<p>Set up shared MCP server configurations that give all team members access to the same enhanced AI capabilities. This might include team-specific servers for your internal APIs, shared database access, or custom tools that understand your deployment pipeline. When everyone has the same AI capabilities, collaboration becomes seamless.</p>
<p><strong>AI-Generated Code Reviews:</strong></p>
<p>Transform your code review process to work effectively with AI-generated code. Establish conventions for tagging AI-generated sections in pull requests - this helps reviewers focus their attention appropriately. Instead of nitpicking syntax that AI typically handles well, reviewers can concentrate on architectural decisions, business logic correctness, and integration patterns that require human judgment.</p>
<p>Implement rigorous testing for AI-generated code, as automated tests catch AI mistakes more reliably than manual review. Create team standards for testing AI output, including edge cases and integration scenarios that AI might miss. This allows you to benefit from AI's speed while maintaining quality through systematic verification.</p>
<p><strong>Document AI tool decisions</strong> in commit messages.</p>
<h4 id="heading-simple-team-setup">Simple Team Setup</h4>
<p>Start small and build up:</p>
<ul>
<li><p>Get everyone using the same AI tools first</p>
</li>
<li><p>Create a shared document of prompts that work well for your projects</p>
</li>
<li><p>Figure out when your team should use Agent Mode vs regular assistance</p>
</li>
<li><p>Set up MCP servers for your most important team tools</p>
</li>
</ul>
<h3 id="heading-for-bigger-projects">For Bigger Projects</h3>
<p>As your projects grow, you might want to:</p>
<ul>
<li><p>Try different AI models for different tasks (fast ones for simple code, powerful ones for complex problems)</p>
</li>
<li><p>Create shortcuts for tasks you do often</p>
</li>
<li><p>Connect AI tools with your existing development workflow</p>
</li>
</ul>
<h3 id="heading-keep-learning">Keep Learning</h3>
<p>AI coding tools improve every month! Stay current by:</p>
<ul>
<li><p>Following the tools' release notes (they email updates)</p>
</li>
<li><p>Joining Discord communities for AI coding</p>
</li>
<li><p>Trying new features as they come out</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congratulations! You now have everything you need to start your AI-assisted coding journey. Remember, every expert was once a beginner, and with AI as your coding partner, you can learn and grow faster than ever before.</p>
<p><strong>Remember:</strong></p>
<ul>
<li><p>AI doesn't replace your creativity – it amplifies it</p>
</li>
<li><p>Every suggestion is a learning opportunity</p>
</li>
<li><p>Mistakes are part of the journey</p>
</li>
<li><p>The community is here to help</p>
</li>
</ul>
<p>You're not just learning to code with AI – you're learning about the future of software development. In a few months, you'll wonder how you ever coded without it. The developers who embrace AI assistance today will be the leaders of tomorrow.</p>
<p>Happy coding! 🚀</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Break Free from Tutorial Hell: A Practical Guide ]]>
                </title>
                <description>
                    <![CDATA[ If you have ever spent weeks hopping from one coding tutorial to another, only to freeze the moment you are asked to build something from scratch, you're not alone. This loop, known as tutorial hell, is where many aspiring developers get stuck. It fe... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-break-free-from-tutorial-hell/</link>
                <guid isPermaLink="false">68af2c4fa028696d3cf7c091</guid>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Tips ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding journey ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #beginners #learningtocode #100daysofcode ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Andrew Ezeani ]]>
                </dc:creator>
                <pubDate>Wed, 27 Aug 2025 16:03:27 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756310586139/70a20570-61f6-4771-b0a9-718573d710f5.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you have ever spent weeks hopping from one coding tutorial to another, only to freeze the moment you are asked to build something from scratch, you're not alone.</p>
<p>This loop, known as tutorial hell, is where many aspiring developers get stuck. It feels productive, but over time, you start to realize you’re not really learning how to think or build like a developer. You’re just getting better at following instructions.</p>
<p>In this guide, I’ll walk you through exactly how to break free from that cycle. This is not a pseudo-motivational guide. It’s practical steps based on personal experience, so you can finally start building projects with confidence.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-tutorials-are-not-enough">Why Tutorials Are Not Enough</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-i-broke-free">How I Broke Free</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-1-accept-that-you-know-nothing-yet">Step 1: Accept That You Know Nothing – Yet</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-start-simple">Step 2: Start Simple</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-break-down-the-project-into-smaller-parts">Step 3: Break Down the Project Into Smaller Parts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-dont-fear-bugs-theyre-signs-of-progress">Step 4: Don’t Fear Bugs – They’re Signs of Progress</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-show-others-your-work">Step 5: Show Others Your Work</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-build-more-similar-projects">Step 6: Build More Similar Projects</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ul>
<h2 id="heading-why-tutorials-are-not-enough">Why Tutorials Are Not Enough</h2>
<p>Tutorials are a great way to get started. They provide structure, simplify complexity, and offer quick wins that make you feel like you’re making progress. In the early stages, that sense of momentum is crucial.</p>
<p>But tutorials can be deceptive. When you’re following along, you’re not solving problems, you’re just replicating solutions that have been worked out for you. It feels productive, but it’s passive learning. You’re learning how to follow instructions, not how to think through a problem or make decisions on your own – that’s the real trap.</p>
<p>Tutorials teach you how to code, but not how to build. You might learn the syntax, but you’re not learning how to build from scratch, troubleshoot unexpected bugs, or take ownership of a project. Over time, after multiple tutorials, this creates a false sense of mastery. It makes you believe that you’re knowledgeable enough, even though you haven’t tested your skills yet.</p>
<p>I know this because I was stuck there too.</p>
<h2 id="heading-how-i-broke-free">How I Broke Free</h2>
<p>Breaking free from tutorial hell was not easy. I had to change my mindset and accept something uncomfortable: I didn’t know as much as I thought I did. That realization stung, but it was freeing. I stopped trying to build big, impressive projects – like a Facebook or Netflix clone – and focused instead on small, achievable ones. Projects that challenged me just enough to learn, but not so much that I would burn out.</p>
<p>I also changed how I approached learning. Instead of trying to absorb everything up front, I started with a goal and only learned what I needed to achieve it. This made my learning process more purposeful and, surprisingly, more enjoyable.</p>
<p>What follows are the exact steps that helped me transition from relying on tutorials to building confidently on my own.</p>
<h3 id="heading-step-1-accept-that-you-know-nothing-yet">Step 1: Accept That You Know Nothing – Yet</h3>
<p>It’s natural to feel confident after completing a few tutorial-based projects. But it’s important to manage your expectations and honestly evaluate your skill level. One pitfall I had was overestimating my ability because of the projects I had built following tutorials.</p>
<p>I had to pause and ask myself an important question: Was the success of those projects dependent on me?</p>
<p>After some reflection, the answer was disappointing but clear – they weren’t. I didn’t possess the knowledge I assumed I had. I was just good at following the carefully laid out instructions from the tutorial.</p>
<p>In hindsight, I realized that building a project is more than just writing code. It involves research, planning, and critical thinking – things tutorials often don’t teach or focus on. Writing code is usually the last thing that’s done. This explains why a common complaint from new developers is, “I know the syntax, but I don’t know what to do when building a project”.</p>
<p>Think of tutorials as training wheels. They help you ride a bicycle (build a project) by providing balance (the tutorial), but they don’t teach you how to maintain that balance on your own. When the training wheels come off – when you try to build independently – you fall off the bicycle because you never learned how to ride one without it.</p>
<p>It’s hard to admit that weeks (or months) of following tutorials have not prepared you as well as you thought. But accepting that truth is the first step toward breaking free from tutorial hell. I had to face this reality, and while it wasn’t easy, that moment of clarity became the turning point in my journey.</p>
<h3 id="heading-step-2-start-simple">Step 2: Start Simple</h3>
<p>Choosing a good first project was tricky. The common advice I got was to build a project I liked or that solved a personal problem. While that sounded reasonable, it didn’t work for me as a beginner. After several failed attempts, I realized those ideas required more knowledge than I had, so it led to frustration and self-doubt.</p>
<p>Problem-solving is a vital skill for programmers, but in the early stages, choosing a project based on a personal problem can be counterproductive. The complexity often outweighs your current abilities, creating unnecessary pressure.</p>
<p>As a beginner, your priority should be building confidence. The easiest way to do that is by starting with simple projects. A simple project is one you can do without feeling overwhelmed. For me, that was <a target="_blank" href="https://www.frontendmentor.io/challenges/qr-code-component-iux_sIO_H">this project</a> on building a QR code generator.</p>
<p>How did I choose it? I used a simple rule: if I looked at the design or the general idea for a project and had no clue on how to build it, I assumed it was beyond my skill level and looked for something simpler. It was not a quick 2-minute decision – I usually gave myself up to 2 two hours to brainstorm. If I was still stuck after that, it was a sign that the project might be too advanced for me.</p>
<p>Platforms like <a target="_blank" href="https://www.frontendmentor.io/">FrontendMentor</a> and <a target="_blank" href="https://icodethis.com/">iCodeThis</a> offer free project designs categorized by difficulty. They helped me focus on writing code without worrying about what to build from scratch.</p>
<p>At this stage, my goal was not to build something impressive – it was to build something that worked.</p>
<h3 id="heading-step-3-break-down-the-project-into-smaller-parts">Step 3: Break Down the Project into Smaller Parts</h3>
<p>When starting a project, it’s easy to feel overwhelmed by its scope. The key to overcoming that feeling is to break up the project into small, manageable pieces. By starting with the easier tasks, you ease into the process, gain momentum, and build confidence before tackling the harder parts.</p>
<p>For my <a target="_blank" href="https://www.frontendmentor.io/solutions/simple-qr-code-component-using-html-and-css-Tba5LCTyD">first project</a>, I divided it into two major sections: the background and the card component. Then I split each section into even smaller parts. Here’s an image of the project:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1755770750207/ec6b3d76-3c2b-4242-96f6-72dc58bdd191.png" alt="A blue QR code on a background with text below encouraging users to improve front-end skills by building projects." width="600" height="400" loading="lazy"></p>
<h3 id="heading-i-started-by-dividing-the-card-component-into-clear-sections">I started by dividing the card component into clear sections:</h3>
<ul>
<li><p>The card background.</p>
</li>
<li><p>The card size.</p>
</li>
<li><p>The card contents.</p>
</li>
</ul>
<p>Then I broke the card contents even further:</p>
<ul>
<li><p>The QR image</p>
</li>
<li><p>The heading text</p>
</li>
<li><p>The subtext</p>
</li>
</ul>
<p>Next, I turned each of those items into a simple to-do list of actionable tasks:</p>
<ol>
<li><p>Add a background color to the body element.</p>
</li>
<li><p>Create the card component.</p>
</li>
<li><p>Give the card a fixed width and height.</p>
</li>
<li><p>Center the card component.</p>
</li>
<li><p>Add the background color of the card component.</p>
</li>
<li><p>Add the QR image.</p>
</li>
<li><p>Add the heading text.</p>
</li>
<li><p>Add the sub-text.</p>
</li>
<li><p>Make the card component responsive.</p>
</li>
</ol>
<p>Here’s how that looked in practice for the first few steps:</p>
<p>Task 1: Add a background color to the body</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">220</span>, <span class="hljs-number">220</span>, <span class="hljs-number">220</span>);
}
</code></pre>
<p>Task 2: Create the card component</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"parent"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- content --&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
</code></pre>
<p>Task 3: Give the card a fixed width and height</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.parent</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">320px</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">500px</span>;
}
</code></pre>
<p>Task 4: Center the card component</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
}
</code></pre>
<p>After this, I continued with the same approach for the remaining tasks: adding the card’s background, QR image, heading text, subtext, and finally making the card responsive.</p>
<p>Each small win built my confidence and kept me motivated to move forward. By the end, the entire project felt much less intimidating because I could see steady progress at every step.</p>
<p>Breaking a project into smaller parts is not just about staying organized – it's about making the project feel doable. Focusing on one small task at a time, I moved steadily towards completing the project.</p>
<p>You can see the full source code for this project on my GitHub: <a target="_blank" href="https://github.com/ezeaniiandrew/Simple-QR-Code-Component/">View the repo here</a>.</p>
<h3 id="heading-step-4-dont-fear-bugs-theyre-signs-of-progress">Step 4: Don’t Fear Bugs – They’re Signs of Progress</h3>
<p>When I finally started building projects, one of the things I dreaded most was encountering an error. Logical errors were fine by me – they were quiet. No red text in the console to feed my insecurities. But those console errors, written in red, were my nightmare. They made me feel like programming wasn’t for me. Like I should give up and do something else.</p>
<p>It took a while, but eventually I learned to see bugs for what they represented at that stage of my journey: signs of progress. Because if I had a bug, it meant I had written enough code for something to go wrong. That was a big step forward from not knowing where to begin.</p>
<p>When you encounter a bug in your code, start by isolating the problem. Check the error message in your console – it’s usually the best clue on what went wrong. Read it carefully to understand what’s causing the issue. If you’re unsure after reading the error message, copy and search the message online. You will likely find solutions on platforms like <a target="_blank" href="https://stackoverflow.com/">Stack Overflow</a>.</p>
<p>Then try out the solutions you find, and once the bug is fixed, take the time to understand both the mistake and the solution. This step is crucial. If you don’t know why the error happened, you are more likely to repeat it.</p>
<p>If there is no error message, you’re likely dealing with a logic bug. Review your code for typos, incorrect variable names, or missed function calls. If everything looks fine, try reverting to the last working version of your project, then reapply your changes one step at a time, testing after each update. This approach helps you pinpoint where the bug was introduced.</p>
<p>If you are still stuck, ask for help. A more experienced developer or a colleague can offer a fresh perspective. If you’re working alone and don’t have anyone to ask, take a break. Go for a walk, or do something completely unrelated. Sometimes, you are just mentally tired, and the solution becomes clear once you return with fresh eyes.</p>
<p>And if nothing works, the project may simply be too complex for your current skill level – and that’s okay. Shift your focus back to something simpler to improve your understanding. You can always return to the project later when you are more experienced.</p>
<h3 id="heading-step-5-show-others-your-work">Step 5: Show Others Your Work</h3>
<p>Learning is hard – and learning without feedback is even harder. In this journey, it’s difficult to thrive in isolation. Sometimes, the difference between crossing the finish line and giving up lies in the people around us. That is why it’s essential, especially in the early stages, to join programming communities and consistently share your work online.</p>
<p>When I started, I was building in a bubble for a while, but I always felt I wasn’t making enough progress. Eventually, I joined a few tech communities – <a target="_blank" href="https://discord.gg/UAfh3qzhYb">Frontend Mentor</a> and <a target="_blank" href="http://javascript.info">Javascript.info</a> on Discord – and that helped me tremendously. I met other developers and even collaborated on a project with two of them. Although the group later dissolved due to circumstances beyond our control, the experience was invaluable.</p>
<p>That project taught me things I couldn’t have learned working alone. I learned how to collaborate with teammates across different time zones, use Git more effectively, resolve merge conflicts, and improve my understanding of the DOM traversal methods.</p>
<p>It’s not an easy step, especially if you are not social media inclined, but it is an important one. These communities are made up of people at different stages of their tech careers. Sharing your struggles and encouraging one another creates a much needed support system. On days when your code doesn’t work and you feel like giving up, these communities will remind you that you are not alone.</p>
<p>Another benefit is access to free code reviews and feedback from more experienced developers. Their insights can accelerate your growth, boost your confidence, and help you approach challenges with a fresh perspective.</p>
<h3 id="heading-step-6-build-more-similar-projects">Step 6: Build More Similar Projects</h3>
<p>Completing your first project is a significant milestone. I remember feeling a strong sense of accomplishment and immediately wanted to take on something more complex. But that decision backfired. The next project I chose, an ecommerce site, was well beyond my current ability. I got stuck halfway, lost momentum, and eventually abandoned it. That experience forced me to reassess how I approached my learning.</p>
<p>I realized that the goal at this stage wasn’t to build something impressive, it was to build consistently. So I returned to simpler projects. I built another card component, landing page, and variations of UI components I had already worked on. These may have seemed repetitive, but each one helped me improve and cement my knowledge. I understood layout better, debugged faster, and wrote cleaner code.</p>
<p>By the time I had built several similar projects, I could feel the difference. I wasn’t just building things, I understood what I was doing and why. The growth gave me the confidence to take on more advanced challenges.</p>
<p>If you’ve just completed your first project, don’t rush to build something complex. Focus on projects that align with your current skill level. Repetition will reinforce what you’ve learned, improve your understanding, and give you the confidence to handle more difficult projects when the time comes.</p>
<h2 id="heading-final-thoughts"><strong>Final Thoughts</strong></h2>
<p>At this point, you have built multiple projects, and your confidence as a developer has grown. That progress deserves acknowledgement. Before jumping into the next big challenge, take time to pause and reflect.</p>
<p>Look back on what you've built. Consider how much you've improved. If there are areas where your approach could have been better, refine them. If not, take a moment to appreciate how far you’ve come. That reflection helps you take stock of what you've learnt and prepares you for what comes next.</p>
<p>When you're ready for your next project, choose it carefully. Choose a project more challenging than your last, but not so complex that it disrupts your momentum. Aim for projects that stretch you just enough to push you forward. Sustainable growth is key.</p>
<p>Breaking free from tutorial hell isn't about quitting tutorials altogether. It's about knowing when to stop relying on them and start thinking for yourself. If you stay consistent and keep building, you will grow into a confident, independent developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Machine Learning System on Serverless Architecture ]]>
                </title>
                <description>
                    <![CDATA[ Let’s say you’ve built a fantastic machine learning model that performs beautifully in notebooks. But a model isn’t truly valuable until it’s in production, serving real users and solving real problems. In this article, you’ll learn how to ship a pro... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-machine-learning-system-on-serverless-architecture/</link>
                <guid isPermaLink="false">68addf802314e8b22eae4655</guid>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ serverless ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kuriko ]]>
                </dc:creator>
                <pubDate>Tue, 26 Aug 2025 16:23:28 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756225357023/04572f1b-b9a7-43e0-aabc-2842faa2703f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Let’s say you’ve built a fantastic machine learning model that performs beautifully in notebooks.</p>
<p>But a model isn’t truly valuable until it’s in production, serving real users and solving real problems.</p>
<p>In this article, you’ll learn how to ship a production-ready ML application built on serverless architecture.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-were-building">What We’re Building</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-ai-pricing-for-retailers">AI Pricing for Retailers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-models">The Models</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tuning-and-training">Tuning and Training</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-prediction">The Prediction</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-performance-validation">Performance Validation</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-the-system-architecture">The System Architecture</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-core-aws-resources-in-the-architecture">Core AWS Resources in the Architecture</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-the-deployment-workflow-in-action">The Deployment Workflow in Action</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-draft-python-scripts">Step 1: Draft Python Scripts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-configure-featuremodel-stores-in-s3">Step 2: Configure Feature/Model Stores in S3</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-create-a-flask-application-with-api-endpoints">Step 3: Create a Flask Application with API Endpoints</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-publish-a-docker-image-to-ecr">Step 4: Publish a Docker Image to ECR</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-create-a-lambda-function">Step 5: Create a Lambda Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-configure-aws-resources">Step 6: Configure AWS Resources</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-building-a-client-application-optional">Building a Client Application (Optional)</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-the-react-application">The React Application</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-final-results">Final Results</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>This project requires some basic experience with:</p>
<ul>
<li><p><strong>Machine Learning / Deep Learning:</strong> The full lifecycle, including data handling, model training, tuning, and validation.</p>
</li>
<li><p><strong>Coding:</strong> Proficiency in Python, with experience using major ML libraries such as PyTorch and Scikit-Learn.</p>
</li>
<li><p><strong>Full-stack deployment:</strong> Experience deploying applications using RESTful APIs.</p>
</li>
</ul>
<h2 id="heading-what-were-building">What We’re Building</h2>
<h3 id="heading-ai-pricing-for-retailers">AI Pricing for Retailers</h3>
<p>This project aims to help a middle-sized retailer compete with large players like Amazon.</p>
<p>Smaller companies often can’t afford significant price discounts, so they can face challenges finding optimal price points as they expand their product lines.</p>
<p>Our goal is to leverage AI models to recommend the best price for a selected product to maximize sales for the retailer, and display it on a client-side user interface (UI):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1755873936847/ecf696ef-e161-4453-a6ad-e97d92ac1677.png" alt="What the UI will look like" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You can explore the UI from <a target="_blank" href="https://kuriko-iwai.vercel.app/online-commerce-intelligence-hub">here</a>.</p>
<h3 id="heading-the-models">The Models</h3>
<p>I’ll train and tune multiple models so that when the primary model fails, a backup model gets loaded to serve predictions.</p>
<ul>
<li><p><strong>Primary Model</strong>: Multi-layered feedforward network (on the <strong>PyTorch</strong> library)</p>
</li>
<li><p><strong>Backup Models (Backups)</strong>: LightGBM, SVR, and Elastic Net (on the <strong>Scikit-Learn</strong> library)</p>
</li>
</ul>
<p>The backup models are prioritized based on learning capabilities.</p>
<h3 id="heading-tuning-and-training">Tuning and Training</h3>
<p>The primary model was trained on a dataset of around 500,000 samples (<a target="_blank" href="https://archive.ics.uci.edu/dataset/352/online+retail">source)</a> and fine-tuned using <code>Optuna</code>'s Bayesian Optimization, with grid search available for further refinement.</p>
<p>The backups are also trained on the same samples and tuned using the <code>Scikit-Optimize</code> framework.</p>
<h3 id="heading-the-prediction">The Prediction</h3>
<p>All models serve predictions on <strong>logged quantity values.</strong></p>
<p>Logarithmic transformations of the quantity data make the distribution denser, which helps models learn patterns more effectively. This is because logarithms reduce the impact of extreme values, or outliers, and can help normalize skewed data.</p>
<h3 id="heading-performance-validation">Performance Validation</h3>
<p>We’ll evaluate model performance using different metrics for the transformed and original data, with a lower value always indicating better performance.</p>
<ul>
<li><p><strong>Logged values</strong>: Mean Squared Error (MSE)</p>
</li>
<li><p><strong>Actual values</strong>: Root Mean Squared Log Error (RMSLE) and Mean Absolute Error (MAE)</p>
</li>
</ul>
<h2 id="heading-the-system-architecture">The System Architecture</h2>
<p>We’re going to build a complete ecosystem around an <strong>AWS Lambda function</strong> to create a scalable ML system:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:4680/0*ulcNtwJeU5EOfhTg.png" alt="Fig. The system architecture (Created by Kuriko IWAI)" width="600" height="400" loading="lazy"></p>
<p>Fig. The system architecture (Created by <a target="_blank" href="https://kuriko-iwai.vercel.app/">Kuriko IWAI)</a></p>
<p><strong>AWS Lambda</strong> is a <strong>serverless production</strong> where a service provider can run the application without managing servers. Once they upload the code, AWS takes on the responsibility of managing the underlying infrastructure.</p>
<p>In the serverless production, the code is deployed as <strong>a stateless function</strong> that runs only when it’s triggered by an event like HTTP requests or scheduled tasks.</p>
<p>This event-driven nature makes serverless production extremely efficient in resource allocation because:</p>
<ul>
<li><p><strong>There’s no server management</strong>: The cloud provider takes care of operational tasks.</p>
</li>
<li><p><strong>You have automatic scaling</strong>: Serverless applications automatically scale up or down based on demand.</p>
</li>
<li><p><strong>You have pay-per-use billing</strong>: Charged for the exact amount of compute resources the application consumes.</p>
</li>
</ul>
<p>Note that other cloud ecosystems like Google Cloud Platform (GCP) and Microsoft Azure offer comprehensive alternatives to AWS. Which one you choose depends on your budget, project type, and familiarity with each ecosystem.</p>
<h3 id="heading-core-aws-resources-in-the-architecture">Core AWS Resources in the Architecture</h3>
<p>The system architecture focuses on the following points:</p>
<ul>
<li><p>The application is fully containerized on Docker for universal accessibility.</p>
</li>
<li><p>The container image is stored in AWS Elastic Container Registry (ECR).</p>
</li>
<li><p>The API Gateway’s REST API endpoints trigger an event to invoke the Lambda function.</p>
</li>
<li><p>The Lambda function loads the container image from ECR and perform inference.</p>
</li>
<li><p>Trained models, processors, and input features are stored in AWS S3 buckets.</p>
</li>
<li><p>A Redis client serves cached analytical data and past predictions stored in the ElastiCache.</p>
</li>
</ul>
<p>And to build the system, we’ll use the following AWS resources:</p>
<ul>
<li><p><strong>Lamda</strong>: Serves a function to perform inference.</p>
</li>
<li><p><strong>API Gateway:</strong> Routes API calls to the Lambda function.</p>
</li>
<li><p><strong>S3 Storage</strong>: Serves feature store and model store.</p>
</li>
<li><p><strong>ElastiCache:</strong> Store cached predictions and analytical data.</p>
</li>
<li><p><strong>ECR</strong>: Stores Docker container images to allow Lambda to pull the image.</p>
</li>
</ul>
<p>Each resource requires configuration. I’ll explore those details in the next section.</p>
<h2 id="heading-the-deployment-workflow-in-action"><strong>The Deployment Workflow in Action</strong></h2>
<p>The deployment workflow involves the following steps:</p>
<ol>
<li><p>Draft data preparation, model training, and serialization scripts</p>
</li>
<li><p>Configure designated feature store and model store in S3</p>
</li>
<li><p>Create a Flask application with API endpoints</p>
</li>
<li><p>Publish a Docker image to ECR</p>
</li>
<li><p>Create a Lambda function</p>
</li>
<li><p>Configure related AWS resources</p>
</li>
</ol>
<p>We’ll now walk through each of these steps to help you fully understand the process.</p>
<p>For your reference, here is the repository structure:</p>
<pre><code class="lang-markdown">.
.venv/                  [.gitignore]    # stores uv venv
│
└── data/               [.gitignore]
│     └──raw/                           # stores raw data
│     └──preprocessed/                  # stores processed data after imputation and engineering
│
└── models/             [.gitignore]    # stores serialized model after training and tuning
│     └──dfn/                           # deep feedforward network
│     └──gbm/                           # light gbm
│     └──en/                            # elastic net
│     └──production/                    # models to be stored in S3 for production use
|
└── notebooks/                          # stores experimentation notebooks
│
└── src/                                # core functions
│     └──<span class="hljs-emphasis">_utils/                        # utility functions
│     └──data_</span>handling/                 # functions to engineer features
│     └──model/                         # functions to train, tune, validate models
│     │     └── sklearn<span class="hljs-emphasis">_model
│     │     └── torch_</span>model
│     │     └── ...
│     └──main.py                        # main script to run the inference locally
│
└──app.py                               # Flask application (API endpoints)
└──pyproject.toml                       # project configuration
└──.env                [.gitignore]     # environment variables
└──uv.lock                              # dependency locking
└──Dockerfile                           # for Docker container image
└──.dockerignore
└──requirements.txt
└──.python-version                      # python version locking (3.12)
</code></pre>
<h3 id="heading-step-1-draft-python-scripts">Step 1: Draft Python Scripts</h3>
<p>The first step is to draft Python scripts for data preparation, model training and tuning.</p>
<p>We’ll run these scripts in a <strong>batch process</strong> because these are resource-intensive and stateful tasks that aren’t suitable for serverless functions optimized for short-lived, stateless, and event-driven tasks.</p>
<p>Serverless functions also can experience <a target="_blank" href="https://www.freecodecamp.org/news/cold-start-problem-in-recommender-systems/"><strong>cold starts</strong></a>. With heavy tasks in the function, the API gateway would timeout before serving predictions.</p>
<p><code>src/main.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">import</span> warnings
<span class="hljs-keyword">import</span> pickle
<span class="hljs-keyword">import</span> joblib
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> lightgbm <span class="hljs-keyword">as</span> lgb
<span class="hljs-keyword">from</span> sklearn.linear_model <span class="hljs-keyword">import</span> ElasticNet
<span class="hljs-keyword">from</span> sklearn.svm <span class="hljs-keyword">import</span> SVR
<span class="hljs-keyword">from</span> skopt.space <span class="hljs-keyword">import</span> Real, Integer, Categorical
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">import</span> src.data_handling <span class="hljs-keyword">as</span> data_handling
<span class="hljs-keyword">import</span> src.model.torch_model <span class="hljs-keyword">as</span> t
<span class="hljs-keyword">import</span> src.model.sklearn_model <span class="hljs-keyword">as</span> sk


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>: 
    load_dotenv(override=<span class="hljs-literal">True</span>)
    os.makedirs(PRODUCTION_MODEL_FOLDER_PATH, exist_ok=<span class="hljs-literal">True</span>)

    <span class="hljs-comment"># create train, validation, test datasets</span>
    X_train, X_val, X_test, y_train, y_val, y_test, preprocessor = data_handling.main_script()

    <span class="hljs-comment"># store the trained preprocessor in local storage</span>
    joblib.dump(preprocessor, PREPROCESSOR_PATH)

    <span class="hljs-comment"># model tuning and training</span>
    best_dfn_full_trained, checkpoint = t.main_script(X_train, X_val, y_train, y_val)

    <span class="hljs-comment"># serialize the trained model</span>
    torch.save(checkpoint, DFN_FILE_PATH)

    <span class="hljs-comment"># svr</span>
    best_svr_trained, best_hparams_svr = sk.main_script(
        X_train, X_val, y_train, y_val, **sklearn_models[<span class="hljs-number">1</span>]
    )
    <span class="hljs-keyword">if</span> best_svr_trained <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        <span class="hljs-keyword">with</span> open(SVR_FILE_PATH, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> f:
            pickle.dump({ <span class="hljs-string">'best_model'</span>: best_svr_trained, <span class="hljs-string">'best_hparams'</span>: best_hparams_svr }, f)

    <span class="hljs-comment"># elastic net</span>
    best_en_trained, best_hparams_en = sk.main_script(
        X_train, X_val, y_train, y_val, **sklearn_models[<span class="hljs-number">0</span>]
    )
    <span class="hljs-keyword">if</span> best_en_trained <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        <span class="hljs-keyword">with</span> open(EN_FILE_PATH, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> f:
            pickle.dump({ <span class="hljs-string">'best_model'</span>: best_en_trained, <span class="hljs-string">'best_hparams'</span>: best_hparams_en }, f)

    <span class="hljs-comment"># light gbm</span>
    best_gbm_trained, best_hparams_gbm = sk.main_script(
        X_train, X_val, y_train, y_val, **sklearn_models[<span class="hljs-number">2</span>]
    )

    <span class="hljs-keyword">if</span> best_gbm_trained <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        <span class="hljs-keyword">with</span> open(GBM_FILE_PATH, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> f:
            pickle.dump({<span class="hljs-string">'best_model'</span>: best_gbm_trained, <span class="hljs-string">'best_hparams'</span>: best_hparams_gbm }, f)
</code></pre>
<p>Run the script to train and serialize the models using the <code>uv</code> package management:</p>
<pre><code class="lang-bash"><span class="hljs-variable">$uv</span> venv
<span class="hljs-variable">$source</span> .venv/bin/activate
<span class="hljs-variable">$uv</span> run src/main.py
</code></pre>
<p>The <code>main.py</code> script includes several key components.</p>
<h4 id="heading-scripts-for-data-handling">Scripts for Data Handling</h4>
<p>These scripts involve loading original data, structure missing values, and engineer features necessary for the future prediction.</p>
<p><code>src/data_handling/main.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> joblib
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split

<span class="hljs-keyword">import</span> src.data_handling.scripts <span class="hljs-keyword">as</span> scripts
<span class="hljs-keyword">from</span> src._utils <span class="hljs-keyword">import</span> main_logger


<span class="hljs-comment"># load and save the original data frame in parquet</span>
df = scripts.load_original_dataframe()
df.to_parquet(ORIGINAL_DF_PATH, index=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># imputation</span>
df = scripts.structure_missing_values(df=df)

<span class="hljs-comment"># feature engineering</span>
df = scripts.handle_feature_engineering(df=df)

<span class="hljs-comment"># save processed df in csv and parquet</span>
scripts.save_df_to_csv(df=df)
df.to_parquet(PROCESSED_DF_PATH, index=<span class="hljs-literal">False</span>)


<span class="hljs-comment"># for preprocessing, classify numerical and categorical columns</span>
num_cols, cat_cols = scripts.categorize_num_cat_cols(df=df, target_col=target_col)
<span class="hljs-keyword">if</span> cat_cols:
    <span class="hljs-keyword">for</span> col <span class="hljs-keyword">in</span> cat_cols: df[col] = df[col].astype(<span class="hljs-string">'string'</span>)

<span class="hljs-comment"># creates training, validation, and test datasets (test dataset is for inference only)</span>
y = df[target_col]
X = df.copy().drop(target_col, axis=<span class="hljs-string">'columns'</span>)
test_size, random_state = <span class="hljs-number">50000</span>, <span class="hljs-number">42</span>
X_tv, X_test, y_tv, y_test = train_test_split(
    X, y, test_size=test_size, random_state=random_state
)
X_train, X_val, y_train, y_val = train_test_split(
    X_tv, y_tv, test_size=test_size, random_state=random_state
)

<span class="hljs-comment"># transform the input datasets</span>
X_train, X_val, X_test, preprocessor = scripts.transform_input(
    X_train, X_val, X_test, num_cols=num_cols, cat_cols=cat_cols
)

<span class="hljs-comment"># retrain and serialize the preprocessor</span>
<span class="hljs-keyword">if</span> preprocessor <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>: preprocessor.fit(X)
joblib.dump(preprocessor, PREPROCESSOR_PATH)
</code></pre>
<h4 id="heading-scripts-for-model-training-and-tuning-pytorch-model">Scripts for Model Training and Tuning (PyTorch Model)</h4>
<p>The scripts involve initiating the model, searching optimal neural architecture and hyperparameters, and serializing the fully-trained model so that the system can load the trained model when performing inference.</p>
<p>Because the primary model is built on PyTorch and the backups use Scikit-Learn, we’re drafting the scripts separately.</p>
<h4 id="heading-1-pytorch-models">1. PyTorch Models</h4>
<p><strong>The training script</strong> contains training the model with the validation over a subset of training data.</p>
<p>It contains the early stopping logic when the loss history is not improved for a given consecutive epochs (that is, 10 epochs).</p>
<p><code>src/model/torch_model/scripts/training.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">import</span> torch.nn <span class="hljs-keyword">as</span> nn
<span class="hljs-keyword">import</span> optuna <span class="hljs-comment"># type: ignore</span>
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split

<span class="hljs-keyword">from</span> src._utils <span class="hljs-keyword">import</span> main_logger

<span class="hljs-comment"># device</span>
device_type = device_type <span class="hljs-keyword">if</span> device_type <span class="hljs-keyword">else</span> <span class="hljs-string">'cuda'</span> <span class="hljs-keyword">if</span> torch.cuda.is_available() <span class="hljs-keyword">else</span> <span class="hljs-string">'mps'</span> <span class="hljs-keyword">if</span> torch.backends.mps.is_available() <span class="hljs-keyword">else</span> <span class="hljs-string">'cpu'</span>
device = torch.device(device_type)

<span class="hljs-comment"># gradient scaler for stability (only applicable for cuba)</span>
scaler = torch.GradScaler(device=device_type) <span class="hljs-keyword">if</span> device_type == <span class="hljs-string">'cuba'</span> <span class="hljs-keyword">else</span> <span class="hljs-literal">None</span>

<span class="hljs-comment"># start training</span>
best_val_loss = float(<span class="hljs-string">'inf'</span>)
epochs_no_improve = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> epoch <span class="hljs-keyword">in</span> range(num_epochs):
    model.train()
    <span class="hljs-keyword">for</span> batch_X, batch_y <span class="hljs-keyword">in</span> train_data_loader:
        batch_X, batch_y = batch_X.to(device), batch_y.to(device)
        optimizer.zero_grad()

        <span class="hljs-keyword">try</span>:
            <span class="hljs-comment"># pytorch's AMP system automatically handles the casting of tensors to Float16 or Float32</span>
            <span class="hljs-keyword">with</span> torch.autocast(device_type=device_type):
                outputs = model(batch_X)
                loss = criterion(outputs, batch_y)

                <span class="hljs-comment"># break the training loop when models return nan or inf</span>
                <span class="hljs-keyword">if</span> torch.any(torch.isnan(outputs)) <span class="hljs-keyword">or</span> torch.any(torch.isinf(outputs)):
                    main_logger.error(
                        <span class="hljs-string">'pytorch model returns nan or inf. break the training loop.'</span>
                    )
                    <span class="hljs-keyword">break</span>

            <span class="hljs-comment"># create scaled gradients of losses</span>
            <span class="hljs-keyword">if</span> scaler <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
                scaler.scale(loss).backward()
                scaler.unscale_(optimizer)  <span class="hljs-comment"># cliping grad</span>
                nn.utils.clip_grad_norm_(model.parameters(), max_norm=<span class="hljs-number">1.0</span>)
                scaler.step(optimizer)  <span class="hljs-comment"># unscales the gradients</span>
                scaler.update()  <span class="hljs-comment"># updates the scale</span>

            <span class="hljs-keyword">else</span>:
                loss.backward()
                nn.utils.clip_grad_norm_(model.parameters(), max_norm=<span class="hljs-number">1.0</span>) <span class="hljs-comment"># cliping grad</span>
                optimizer.step()

        <span class="hljs-keyword">except</span>:
            outputs = model(batch_X)
            loss = criterion(outputs, batch_y)
            loss.backward()
            optimizer.step()


    <span class="hljs-comment"># run validation on a subset of the training dataset</span>
    model.eval()
    val_loss = <span class="hljs-number">0.0</span>

    <span class="hljs-comment"># switch the torch mode</span>
    <span class="hljs-keyword">with</span> torch.inference_mode():
        <span class="hljs-keyword">for</span> batch_X_val, batch_y_val <span class="hljs-keyword">in</span> val_data_loader:
            batch_X_val, batch_y_val = batch_X_val.to(device), batch_y_val.to(device)
            outputs_val = model(batch_X_val)
            val_loss += criterion(outputs_val, batch_y_val).item()

    val_loss /= len(val_data_loader)

    <span class="hljs-comment"># check if early stop</span>
    <span class="hljs-keyword">if</span> val_loss &lt; best_val_loss - min_delta:
        best_val_loss = val_loss
        epochs_no_improve = <span class="hljs-number">0</span>
    <span class="hljs-keyword">else</span>:
        epochs_no_improve += <span class="hljs-number">1</span>
        <span class="hljs-keyword">if</span> epochs_no_improve &gt;= patience:
            main_logger.info(<span class="hljs-string">f'early stopping at epoch <span class="hljs-subst">{epoch + <span class="hljs-number">1</span>}</span>'</span>)
            <span class="hljs-keyword">break</span>
</code></pre>
<p><strong>The tuning script</strong> uses the <code>study</code> component from the <code>Optuna</code> library to run the Bayesian Optimization.</p>
<p>The <code>study</code> component choose a neural architecture and hyperparameter set to test from the global search space.</p>
<p>Then, it builds, trains, and validates the model to find the optimal neural architecture that can minimize the loss (MSE, for instance).</p>
<p><code>src/model/torch_model/scripts/tuning.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> itertools
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> optuna
<span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">import</span> torch.nn <span class="hljs-keyword">as</span> nn
<span class="hljs-keyword">import</span> torch.optim <span class="hljs-keyword">as</span> optim
<span class="hljs-keyword">from</span> torch.utils.data <span class="hljs-keyword">import</span> DataLoader, TensorDataset
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split

<span class="hljs-keyword">from</span> src.model.torch_model.scripts.pretrained_base <span class="hljs-keyword">import</span> DFN
<span class="hljs-keyword">from</span> src.model.torch_model.scripts.training <span class="hljs-keyword">import</span> train_model
<span class="hljs-keyword">from</span> src._utils <span class="hljs-keyword">import</span> main_logger

<span class="hljs-comment"># device</span>
device_type = <span class="hljs-string">"cuda"</span> <span class="hljs-keyword">if</span> torch.cuda.is_available() <span class="hljs-keyword">else</span> <span class="hljs-string">"mps"</span> <span class="hljs-keyword">if</span> torch.backends.mps.is_available() <span class="hljs-keyword">else</span> <span class="hljs-string">"cpu"</span>
device = torch.device(device_type)

<span class="hljs-comment"># loss function</span>
criterion = nn.MSELoss()

<span class="hljs-comment"># define objective function for optuna</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">objective</span>(<span class="hljs-params">trial</span>):</span>
    <span class="hljs-comment"># model</span>
    num_layers = trial.suggest_int(<span class="hljs-string">'num_layers'</span>, <span class="hljs-number">1</span>, <span class="hljs-number">20</span>)
    batch_norm = trial.suggest_categorical(<span class="hljs-string">'batch_norm'</span>, [<span class="hljs-literal">True</span>, <span class="hljs-literal">False</span>])
    dropout_rates = []
    hidden_units_per_layer = []
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(num_layers):
        dropout_rates.append(trial.suggest_float(<span class="hljs-string">f'dropout_rate_layer_<span class="hljs-subst">{i}</span>'</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">0.6</span>))
        hidden_units_per_layer.append(trial.suggest_int(<span class="hljs-string">f'n_units_layer_<span class="hljs-subst">{i}</span>'</span>, <span class="hljs-number">8</span>, <span class="hljs-number">256</span>)) <span class="hljs-comment"># hidden units per layer</span>

    model = DFN(
        input_dim=X_train.shape[<span class="hljs-number">1</span>],
        num_layers=num_layers,
        dropout_rates=dropout_rates,
        batch_norm=batch_norm,
        hidden_units_per_layer=hidden_units_per_layer
    ).to(device)

    <span class="hljs-comment"># optimizer</span>
    learning_rate = trial.suggest_float(<span class="hljs-string">'learning_rate'</span>, <span class="hljs-number">1e-10</span>, <span class="hljs-number">1e-1</span>, log=<span class="hljs-literal">True</span>)
    optimizer_name = trial.suggest_categorical(<span class="hljs-string">'optimizer'</span>, [<span class="hljs-string">'adam'</span>, <span class="hljs-string">'rmsprop'</span>, <span class="hljs-string">'sgd'</span>, <span class="hljs-string">'adamw'</span>, <span class="hljs-string">'adamax'</span>, <span class="hljs-string">'adadelta'</span>, <span class="hljs-string">'radam'</span>])
    optimizer = _handle_optimizer(optimizer_name=optimizer_name, model=model, lr=learning_rate)

    <span class="hljs-comment"># data loaders</span>
    batch_size = trial.suggest_categorical(<span class="hljs-string">'batch_size'</span>, [<span class="hljs-number">32</span>, <span class="hljs-number">64</span>, <span class="hljs-number">128</span>, <span class="hljs-number">256</span>])
    test_size = <span class="hljs-number">10000</span> <span class="hljs-keyword">if</span> len(X_train) &gt; <span class="hljs-number">15000</span> <span class="hljs-keyword">else</span> int(len(X_train) * <span class="hljs-number">0.2</span>)
    X_train_search, X_val_search, y_train_search, y_val_search = train_test_split(X_train, y_train, test_size=test_size, random_state=<span class="hljs-number">42</span>)
    train_data_loader = create_torch_data_loader(X=X_train_search, y=y_train_search, batch_size=batch_size)
    val_data_loader = create_torch_data_loader(X=X_val_search, y=y_val_search, batch_size=batch_size)

    <span class="hljs-comment"># training</span>
    num_epochs = <span class="hljs-number">3000</span> <span class="hljs-comment"># ensure enough epochs (early stopping would stop the loop when overfitting)</span>
    _, best_val_loss = train_model(
        train_data_loader=train_data_loader,
        val_data_loader=val_data_loader,
        model=model,
        optimizer=optimizer,
        criterion = criterion,
        num_epochs=num_epochs,
        trial=trial,
    )
    <span class="hljs-keyword">return</span> best_val_loss


<span class="hljs-comment"># start to optimize hyperparameters and architecture</span>
study = optuna.create_study(direction=<span class="hljs-string">'minimize'</span>, sampler=optuna.samplers.TPESampler())
study.optimize(objective, n_trials=<span class="hljs-number">50</span>, timeout=<span class="hljs-number">600</span>)

<span class="hljs-comment"># best </span>
best_trial = study.best_trial
best_hparams = best_trial.params

<span class="hljs-comment"># construct the model based on the tuning results</span>
best_lr = best_hparams[<span class="hljs-string">'learning_rate'</span>]
best_batch_size = best_hparams[<span class="hljs-string">'batch_size'</span>]
input_dim = X_train.shape[<span class="hljs-number">1</span>]
best_model = DFN(
    input_dim=input_dim,
    num_layers=best_hparams[<span class="hljs-string">'num_layers'</span>],
    hidden_units_per_layer=[v <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> best_hparams.items() <span class="hljs-keyword">if</span> <span class="hljs-string">'n_units_layer_'</span> <span class="hljs-keyword">in</span> k],
    batch_norm=best_hparams[<span class="hljs-string">'batch_norm'</span>],
    dropout_rates=[v <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> best_hparams.items() <span class="hljs-keyword">if</span> <span class="hljs-string">'dropout_rate_layer_'</span> <span class="hljs-keyword">in</span> k],
).to(device)

<span class="hljs-comment"># construct an optimizer based on the tuning results</span>
best_optimizer_name = best_hparams[<span class="hljs-string">'optimizer'</span>]
best_optimizer = _handle_optimizer(
    optimizer_name=best_optimizer_name, model=best_model, lr=best_lr
)

<span class="hljs-comment"># create torch data loaders</span>
train_data_loader = create_torch_data_loader(
    X=X_train, y=y_train, batch_size=best_batch_size
)
val_data_loader = create_torch_data_loader(
    X=X_val, y=y_val, batch_size=best_batch_size
)

<span class="hljs-comment"># retrain the best model with full training dataset applying the optimal batch size and optimizer</span>
best_model, _ = train_model(
    train_data_loader=train_data_loader,
    val_data_loader=val_data_loader,
    model=best_model,
    optimizer=best_optimizer,
    criterion = criterion,
    num_epochs=<span class="hljs-number">1000</span>
)

<span class="hljs-comment"># create a checkpoint for serialization (reconstruct the model using the checkpoint)</span>
checkpoint = {
    <span class="hljs-string">'state_dict'</span>: best_model.state_dict(),
    <span class="hljs-string">'hparams'</span>: best_hparams,
    <span class="hljs-string">'input_dim'</span>: X_train.shape[<span class="hljs-number">1</span>],
    <span class="hljs-string">'optimizer'</span>: best_optimizer,
    <span class="hljs-string">'batch_size'</span>: best_batch_size
}

<span class="hljs-comment"># serialize the model w/ checkpoint</span>
torch.save(checkpoint, FILE_PATH)
</code></pre>
<h4 id="heading-2-scikit-learn-models-backups">2. Scikit-Learn Models (Backups)</h4>
<p>For Scikit-Learn models, we’ll run <strong>k-fold cross validation</strong> during training to prevent overfitting.</p>
<p>K-fold cross-validation is a technique for evaluating a machine learning model's performance by training and testing it on different subsets of training data.</p>
<p>We define the <code>run_kfold_validation</code> function where the model is trained and validated using <strong>5-fold cross-validation</strong>.</p>
<p><code>src/model/sklearn_model/scripts/tuning.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> KFold
<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> mean_squared_error

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run_kfold_validation</span>(<span class="hljs-params">
        X_train,
        y_train,
        base_model,
        hparams: dict,
        n_splits: int = <span class="hljs-number">5</span>, <span class="hljs-comment"># the number of folds </span>
        early_stopping_rounds: int = <span class="hljs-number">10</span>,
        max_iters: int = <span class="hljs-number">200</span>
    </span>) -&gt; float:</span>

    mses = <span class="hljs-number">0.0</span>

    <span class="hljs-comment"># create k-fold component</span>
    kf = KFold(n_splits=n_splits, shuffle=<span class="hljs-literal">True</span>, random_state=<span class="hljs-number">42</span>)

    <span class="hljs-keyword">for</span> fold, (train_index, val_index) <span class="hljs-keyword">in</span> enumerate(kf.split(X_train)):
        <span class="hljs-comment"># create a subset of training and validation datasets from the entire training data</span>
        X_train_fold, X_val_fold = X_train.iloc[train_index], X_train.iloc[val_index]
        y_train_fold, y_val_fold = y_train.iloc[train_index], y_train.iloc[val_index]

        <span class="hljs-comment"># reconstruct a model</span>
        model = base_model(**hparams)

        <span class="hljs-comment"># start the cross validation</span>
        best_val_mse = float(<span class="hljs-string">'inf'</span>)
        patience_counter = <span class="hljs-number">0</span>
        best_model_state = <span class="hljs-literal">None</span>
        best_iteration = <span class="hljs-number">0</span>

        <span class="hljs-keyword">for</span> iteration <span class="hljs-keyword">in</span> range(max_iters):
            <span class="hljs-comment"># train on a subset of the training data</span>
            <span class="hljs-keyword">try</span>:
                model.train_one_step(X_train_fold, y_train_fold, iteration)
            <span class="hljs-keyword">except</span>:
                model.fit(X_train_fold, y_train_fold)

            <span class="hljs-comment"># make a prediction on validation data </span>
            y_pred_val_kf = model.predict(X_val_fold)

            <span class="hljs-comment"># compute validation loss (MSE)</span>
            current_val_mse = mean_squared_error(y_val_fold, y_pred_val_kf)

            <span class="hljs-comment"># check if epochs should be stopped (early stopping)</span>
           <span class="hljs-keyword">if</span> current_val_mse &lt; best_val_mse:
                best_val_mse = current_val_mse
                patience_counter = <span class="hljs-number">0</span>
                best_model_state = model.get_params()
                best_iteration = iteration
           <span class="hljs-keyword">else</span>:
                patience_counter += <span class="hljs-number">1</span>

           <span class="hljs-comment"># execute early stopping when patience_counter exceeds early_stopping_rounds</span>
           <span class="hljs-keyword">if</span> patience_counter &gt;= early_stopping_rounds:
                main_logger.info(<span class="hljs-string">f"Fold <span class="hljs-subst">{fold}</span>: Early stopping triggered at iteration <span class="hljs-subst">{iteration}</span> (best at <span class="hljs-subst">{best_iteration}</span>). Best MSE: <span class="hljs-subst">{best_val_mse:<span class="hljs-number">.4</span>f}</span>"</span>)
                <span class="hljs-keyword">break</span>


        <span class="hljs-comment"># after training epochs, reconstruct the best performing model </span>
        <span class="hljs-keyword">if</span> best_model_state: model.set_params(**best_model_state)

        <span class="hljs-comment"># make prediction</span>
        y_pred_val_kf = model.predict(X_val_fold)

        <span class="hljs-comment"># add MSEs</span>
        mses += mean_squared_error(y_pred_val_kf, y_val_fold)

    <span class="hljs-comment"># compute the final loss (avarage of MSEs across folds)</span>
    ave_mse = mses / n_splits
    <span class="hljs-keyword">return</span> ave_mse
</code></pre>
<p>Then, for the <strong>tuning script</strong>, we use the <code>gp_minimize</code> function from the <code>Scikit-Optimize</code> library.</p>
<p>The <code>gp_minimize</code> function is used to tune hyperparameters with Bayesian optimization.</p>
<p>This function intelligently searches the best hyperparameter set that can minimize the model's error, which is calculated using the <code>run_kfold_validation</code> function defined earlier.</p>
<p>The best-performing hyperparameters are then used to reconstruct and train the final model.</p>
<p><code>src/model/sklearn_model/scripts/tuning.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> partial
<span class="hljs-keyword">from</span> skopt <span class="hljs-keyword">import</span> gp_minimize


<span class="hljs-comment"># define the objective function for Bayesian Optimization using Scikit-Optimize</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">objective</span>(<span class="hljs-params">params, X_train, y_train, base_model, hparam_names</span>):</span>
    hparams = {item: params[i] <span class="hljs-keyword">for</span> i, item <span class="hljs-keyword">in</span> enumerate(hparam_names)}
    ave_mse = run_kfold_validation(X_train=X_train, y_train=y_train, base_model=base_model, hparams=hparams)
    <span class="hljs-keyword">return</span> ave_mse

<span class="hljs-comment"># create the search space</span>
hparam_names = [s.name <span class="hljs-keyword">for</span> s <span class="hljs-keyword">in</span> space]
objective_partial = partial(objective, X_train=X_train, y_train=y_train, base_model=base_model, hparam_names=hparam_names)

<span class="hljs-comment"># search the optimal hyperparameters</span>
results = gp_minimize(
    func=objective_partial,
    dimensions=space,
    n_calls=n_calls,
    random_state=<span class="hljs-number">42</span>,
    verbose=<span class="hljs-literal">False</span>,
    n_initial_points=<span class="hljs-number">10</span>,
)
<span class="hljs-comment"># results</span>
best_hparams = dict(zip(hparam_names, results.x))
best_mse = results.fun

<span class="hljs-comment"># reconstruct the model with the best hyperparameters</span>
best_model = base_model(**best_hparams)

<span class="hljs-comment"># retrain the model with full training dataset</span>
best_model.fit(X_train, y_train)
</code></pre>
<h3 id="heading-step-2-configure-featuremodel-stores-in-s3">Step 2: Configure Feature/Model Stores in S3</h3>
<p>The trained models and processed data are stored in the S3 bucket as a <strong>Parquet file</strong>.</p>
<p>We’ll draft the <code>s3_upload</code> function where the <strong>Boto3 client</strong>, a low-level interface to an AWS service, initiates the connection to S3:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> boto3
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> src._utils <span class="hljs-keyword">import</span> main_logger

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">s3_upload</span>(<span class="hljs-params">file_path: str</span>):</span>
    <span class="hljs-comment"># initiate the boto3 client</span>
    load_dotenv(override=<span class="hljs-literal">True</span>)
    S3_BUCKET_NAME = os.environ.get(<span class="hljs-string">'S3_BUCKET_NAME'</span>) <span class="hljs-comment"># the bucket created in s3</span>
    s3_client = boto3.client(<span class="hljs-string">'s3'</span>, region_name=os.environ.get(<span class="hljs-string">'AWS_REGION_NAME'</span>)) <span class="hljs-comment"># your default region</span>

    <span class="hljs-keyword">if</span> s3_client:
        <span class="hljs-comment"># create s3 key and upload the file to the bucket</span>
        s3_key = file_path <span class="hljs-keyword">if</span> file_path[<span class="hljs-number">0</span>] != <span class="hljs-string">'/'</span> <span class="hljs-keyword">else</span> file_path[<span class="hljs-number">1</span>:]
        s3_client.upload_file(file_path, S3_BUCKET_NAME, s3_key)
        main_logger.info(<span class="hljs-string">f"file uploaded to s3://<span class="hljs-subst">{S3_BUCKET_NAME}</span>/<span class="hljs-subst">{s3_key}</span>"</span>)
    <span class="hljs-keyword">else</span>:
        main_logger.error(<span class="hljs-string">'failed to create an S3 client.'</span>)
</code></pre>
<h4 id="heading-model-store">Model Store</h4>
<p>Trained PyTorch models are serialized (converted) into <code>.pth</code> files.</p>
<p>Then, these files are uploaded to the S3 bucket, enabling the system to load the trained model when it performs inference in production.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> torch

<span class="hljs-keyword">from</span> src._utils <span class="hljs-keyword">import</span> s3_upload

<span class="hljs-comment"># model serialization, store in local</span>
torch.save(trained_model.state_dict(), MODEL_FILE_PATH)

<span class="hljs-comment"># upload to s3 model store</span>
s3_upload(file_path=MODEL_FILE_PATH)
</code></pre>
<h4 id="heading-feature-store">Feature Store</h4>
<p>The processed data is converted into a CSV and Parquet file format.</p>
<p>Then, the Parquet files are uploaded to the S3 bucket, enabling the system to load the lightweight data when it creates prediction data to perform inference in production.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> src._utils <span class="hljs-keyword">import</span> s3_upload

<span class="hljs-comment"># store csv and parquet files in local</span>
df.to_csv(file_path, index=<span class="hljs-literal">False</span>)
df.to_parquet(DATA_FILE_PATH, index=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># store in s3 feature store</span>
s3_upload(file_path=DATA_FILE_PATH)

<span class="hljs-comment"># trained preprocessor is also stored to transform the prediction data</span>
s3_upload(file_path=PROCESSOR_PATH)
</code></pre>
<h3 id="heading-step-3-create-a-flask-application-with-api-endpoints">Step 3: Create a Flask Application with API Endpoints</h3>
<p>Next, we’ll create a Flask application with API endpoints.</p>
<p>Flask needs to configure Python scripts in the <code>app.py</code> file located at the root of the project repository.</p>
<p>As showed in the code snippets, the <code>app.py</code> file needs to contain the components in order of:</p>
<ol>
<li><p>AWS Boto3 client setup,</p>
</li>
<li><p>Flask app configuration and API endpoint setup,</p>
</li>
<li><p>Loading the trained preprocessor, processed input data <code>X_test</code>, and trained models,</p>
</li>
<li><p>Invoke the Lambda function via API Gateway, and</p>
</li>
<li><p>The local test section.</p>
</li>
</ol>
<p>Note that <code>X_test</code> should never be used during model training to avoid data leakage.</p>
<p><code>app.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask_cors <span class="hljs-keyword">import</span> cross_origin
<span class="hljs-keyword">from</span> waitress <span class="hljs-keyword">import</span> serve
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv

<span class="hljs-keyword">from</span> src._utils <span class="hljs-keyword">import</span> main_logger

<span class="hljs-comment"># global variables (will be loaded from the S3 buckets)</span>
_redis_client = <span class="hljs-literal">None</span>
X_test = <span class="hljs-literal">None</span>
preprocessor = <span class="hljs-literal">None</span>
model = <span class="hljs-literal">None</span>
backup_model = <span class="hljs-literal">None</span>

<span class="hljs-comment"># load env if local else skip (lambda refers to env in production)</span>
AWS_LAMBDA_RUNTIME_API = os.environ.get(<span class="hljs-string">'AWS_LAMBDA_RUNTIME_API'</span>, <span class="hljs-literal">None</span>)
<span class="hljs-keyword">if</span> AWS_LAMBDA_RUNTIME_API <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>: load_dotenv(override=<span class="hljs-literal">True</span>)


<span class="hljs-comment">#### &lt;---- 1. AWS BOTO3 CLIENT ----&gt;</span>
<span class="hljs-comment"># boto3 client </span>
S3_BUCKET_NAME = os.environ.get(<span class="hljs-string">'S3_BUCKET_NAME'</span>, <span class="hljs-string">'ml-sales-pred'</span>)
s3_client = boto3.client(<span class="hljs-string">'s3'</span>, region_name=os.environ.get(<span class="hljs-string">'AWS_REGION_NAME'</span>, <span class="hljs-string">'us-east-1'</span>))
<span class="hljs-keyword">try</span>:
    <span class="hljs-comment"># test connection to boto3 client</span>
    sts_client = boto3.client(<span class="hljs-string">'sts'</span>)
    identity = sts_client.get_caller_identity()
    main_logger.info(<span class="hljs-string">f"Lambda is using role: <span class="hljs-subst">{identity[<span class="hljs-string">'Arn'</span>]}</span>"</span>)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    main_logger.error(<span class="hljs-string">f"Lambda credentials/permissions error: <span class="hljs-subst">{e}</span>"</span>)

<span class="hljs-comment">#### &lt;---- 2. FLASK CONFIGURATION &amp; API ENDPOINTS ----&gt;</span>
<span class="hljs-comment"># configure the flask app</span>
app = Flask(__name__)
app.config[<span class="hljs-string">'CORS_HEADERS'</span>] = <span class="hljs-string">'Content-Type'</span>

<span class="hljs-comment"># add a simple API endpoint to serve the prediction by price point to test</span>
<span class="hljs-meta">@app.route('/v1/predict-price/&lt;string:stockcode&gt;', methods=['GET', 'OPTIONS'])</span>
<span class="hljs-meta">@cross_origin(origins=origins, methods=['GET', 'OPTIONS'], supports_credentials=True)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">predict_price</span>(<span class="hljs-params">stockcode</span>):</span>
    df_stockcode = <span class="hljs-literal">None</span>

    <span class="hljs-comment"># fetch request params</span>
    data = request.args.to_dict()

    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># fetch cache</span>
        <span class="hljs-keyword">if</span> _redis_client <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
            <span class="hljs-comment"># returns cached prediction results if any without performing inference</span>
            cached_prediction_result = _redis_client.get(cache_key_prediction_result_by_stockcode)
            <span class="hljs-keyword">if</span> cached_prediction_result: 
                <span class="hljs-keyword">return</span> jsonify(json.loads(json.dumps(cached_prediction_result)))

            <span class="hljs-comment"># historical data of the selected product</span>
            cached_df_stockcode = _redis_client.get(cache_key_df_stockcode)
            <span class="hljs-keyword">if</span> cached_df_stockcode: df_stockcode = json.loads(json.dumps(cached_df_stockcode))


        <span class="hljs-comment"># define the price range to make predictions. can be a request param, or historical min/max prices</span>
        min_price = float(data.get(<span class="hljs-string">'unitprice_min'</span>, df_stockcode[<span class="hljs-string">'unitprice_min'</span>][<span class="hljs-number">0</span>]))
        max_price = float(data.get(<span class="hljs-string">'unitprice_max'</span>, df_stockcode[<span class="hljs-string">'unitprice_max'</span>][<span class="hljs-number">0</span>]))

        <span class="hljs-comment"># create bins in the price range. when the number of the bins increase, the prediction becomes more smooth, but requires more computational cost</span>
        NUM_PRICE_BINS = int(data.get(<span class="hljs-string">'num_price_bins'</span>, <span class="hljs-number">100</span>))
        price_range = np.linspace(min_price, max_price, NUM_PRICE_BINS)

        <span class="hljs-comment"># create a prediction dataset by merging X_test (dataset never used in model training) and df_stockcode</span>
        price_range_df = pd.DataFrame({ <span class="hljs-string">'unitprice'</span>: price_range })
        test_sample = X_test.sample(n=<span class="hljs-number">1000</span>, random_state=<span class="hljs-number">42</span>)
        test_sample_merged = test_sample.merge(price_range_df, how=<span class="hljs-string">'cross'</span>) <span class="hljs-keyword">if</span> X_test <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">else</span> price_range_df
        test_sample_merged.drop(<span class="hljs-string">'unitprice_x'</span>, axis=<span class="hljs-number">1</span>, inplace=<span class="hljs-literal">True</span>)
        test_sample_merged.rename(columns={<span class="hljs-string">'unitprice_y'</span>: <span class="hljs-string">'unitprice'</span>}, inplace=<span class="hljs-literal">True</span>)

        <span class="hljs-comment"># preprocess the dataset</span>
        X = preprocessor.transform(test_sample_merged) <span class="hljs-keyword">if</span> preprocessor <span class="hljs-keyword">else</span> test_sample_merged

        <span class="hljs-comment"># perform inference</span>
        y_pred_actual = <span class="hljs-literal">None</span>
        epsilon = <span class="hljs-number">0</span>
        <span class="hljs-comment"># try using the primary model</span>
        <span class="hljs-keyword">if</span> model:
            input_tensor = torch.tensor(X, dtype=torch.float32)
            model.eval()
            <span class="hljs-keyword">with</span> torch.inference_mode():
                y_pred = model(input_tensor)
                y_pred = y_pred.cpu().numpy().flatten()
                y_pred_actual = np.exp(y_pred + epsilon)

        <span class="hljs-comment"># if not, use backups</span>
        <span class="hljs-keyword">elif</span> backup_model:
            y_pred = backup_model.predict(X)
            y_pred_actual = np.exp(y_pred + epsilon)


        <span class="hljs-comment"># finalize the outcome for client app</span>
        df_ = test_sample_merged.copy()
        df_[<span class="hljs-string">'quantity'</span>] = np.floor(y_pred_actual) <span class="hljs-comment"># quantity must be an integer</span>
        df_[<span class="hljs-string">'sales'</span>] = df_[<span class="hljs-string">'quantity'</span>] * df_[<span class="hljs-string">'unitprice'</span>] <span class="hljs-comment"># compute sales</span>
        df_ = df_.sort_values(by=<span class="hljs-string">'unitprice'</span>)

        <span class="hljs-comment"># aggregate the results by the unitprice in the price range</span>
        df_results = df_.groupby(<span class="hljs-string">'unitprice'</span>).agg(
            quantity=(<span class="hljs-string">'quantity'</span>, <span class="hljs-string">'median'</span>),
            quantity_min=(<span class="hljs-string">'quantity'</span>, <span class="hljs-string">'min'</span>),
            quantity_max=(<span class="hljs-string">'quantity'</span>, <span class="hljs-string">'max'</span>),
            sales=(<span class="hljs-string">'sales'</span>, <span class="hljs-string">'median'</span>),
        ).reset_index()

        <span class="hljs-comment"># find the optimal price point</span>
        optimal_row = df_results.loc[df_results[<span class="hljs-string">'sales'</span>].idxmax()]
        optimal_price = optimal_row[<span class="hljs-string">'unitprice'</span>]
        optimal_quantity = optimal_row[<span class="hljs-string">'quantity'</span>]
        best_sales = optimal_row[<span class="hljs-string">'sales'</span>]

        all_outputs = []
        <span class="hljs-keyword">for</span> _, row <span class="hljs-keyword">in</span> df_results.iterrows():
            current_output = {
                <span class="hljs-string">"stockcode"</span>: stockcode,
                <span class="hljs-string">"unit_price"</span>: float(row[<span class="hljs-string">'unitprice'</span>]),
                <span class="hljs-string">'quantity'</span>: int(row[<span class="hljs-string">'quantity'</span>]),
                <span class="hljs-string">'quantity_min'</span>: int(row[<span class="hljs-string">'quantity_min'</span>]),
                <span class="hljs-string">'quantity_max'</span>: int(row[<span class="hljs-string">'quantity_max'</span>]),
                <span class="hljs-string">"predicted_sales"</span>: float(row[<span class="hljs-string">'sales'</span>]),
            }
            all_outputs.append(current_output)

        <span class="hljs-comment"># store the prediction results in cache</span>
        <span class="hljs-keyword">if</span> all_outputs <span class="hljs-keyword">and</span> _redis_client <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
             serialized_data = json.dumps(all_outputs)
            _redis_client.set(
                cache_key_prediction_result_by_stockcode, 
                serialized_data,
                ex=<span class="hljs-number">3600</span>     <span class="hljs-comment"># expire in an hour</span>
            )

        <span class="hljs-comment"># return a list of all outputs</span>
        <span class="hljs-keyword">return</span> jsonify(all_outputs)

    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e: <span class="hljs-keyword">return</span> jsonify([])


<span class="hljs-comment"># request header management (for the process from API gateway to the Lambda)</span>
<span class="hljs-meta">@app.after_request</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_header</span>(<span class="hljs-params">response</span>):</span>
    response.headers[<span class="hljs-string">'Cache-Control'</span>] = <span class="hljs-string">'public, max-age=0'</span>
    response.headers[<span class="hljs-string">'Access-Control-Allow-Origin'</span>] = CLIENT_A
    response.headers[<span class="hljs-string">'Access-Control-Allow-Headers'</span>] = <span class="hljs-string">'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Origin'</span>
    response.headers[<span class="hljs-string">'Access-Control-Allow-Methods'</span>] = <span class="hljs-string">'GET, POST, OPTIONSS'</span>
    response.headers[<span class="hljs-string">'Access-Control-Allow-Credentials'</span>] = <span class="hljs-string">'true'</span>
    <span class="hljs-keyword">return</span> response

<span class="hljs-comment">#### &lt;---- 3. LOADING PROCESSOR, DATASET, AND MODELS ----&gt;</span>
load_processor()
load_x_test()
load_model()

<span class="hljs-comment">#### &lt;---- 4. INVOKE LAMBDA ----&gt;</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">handler</span>(<span class="hljs-params">event, context</span>):</span>
    logger.info(<span class="hljs-string">"lambda handler invoked."</span>)
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># connecting the redis client after the lambda is invoked</span>
        get_redis_client()
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        logger.critical(<span class="hljs-string">f"failed to establish initial Redis connection in handler: <span class="hljs-subst">{e}</span>"</span>)
        <span class="hljs-keyword">return</span> {
            <span class="hljs-string">'statusCode'</span>: <span class="hljs-number">500</span>,
            <span class="hljs-string">'body'</span>: json.dumps({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Failed to initialize Redis client. Check environment variables and network config.'</span>})
        }

    <span class="hljs-comment"># use the awsgi package to convert JSON to WSGI</span>
    <span class="hljs-keyword">return</span> awsgi.response(app, event, context)


<span class="hljs-comment">#### &lt;---- 5. FOR LOCAL TEST ----&gt;</span>
<span class="hljs-comment"># serve the application locally on WSGI server, waitress</span>
<span class="hljs-comment"># lambda will ignore this section.</span>
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:   
    <span class="hljs-keyword">if</span> os.getenv(<span class="hljs-string">'ENV'</span>) == <span class="hljs-string">'local'</span>:
        main_logger.info(<span class="hljs-string">"...start the operation (local)..."</span>)
        serve(app, host=<span class="hljs-string">'0.0.0.0'</span>, port=<span class="hljs-number">5002</span>)
    <span class="hljs-keyword">else</span>:
        app.run(host=<span class="hljs-string">'0.0.0.0'</span>, port=<span class="hljs-number">8080</span>)
</code></pre>
<p>I’ll test the endpoint locally using the <code>uv</code> package manager:</p>
<pre><code class="lang-python">$uv run app.py --cache-clear

$curl http://localhost:<span class="hljs-number">5002</span>/v1/predict-price/{STOCKCODE}
</code></pre>
<p>The system provided a list of sales predictions for each price point:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1755607075000/e0e8cbcb-8817-4aa5-b3d1-37b76cc684fb.png" alt="Fig. Screenshot of the Flask app local response" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Fig. Screenshot of the Flask app local response</p>
<h4 id="heading-key-points-on-flask-app-configuration">Key Points on Flask App Configuration</h4>
<p>There are various points you should take into consideration when configuring a Flask application with Lambda. Let’s go over them now:</p>
<h5 id="heading-1-a-few-api-endpoints-per-container"><strong>1. A Few API Endpoints Per Container</strong></h5>
<p>Adding many API endpoints to a single serverless instance can lead to <strong>monolithic function concern</strong> where issues in one endpoint impact others.</p>
<p>In this project, we’ll focus on a single endpoint per container – and if needed, we can add separate Lambda functions to the system.</p>
<h5 id="heading-2-understanding-the-handler-function-and-the-role-of-awsgi"><strong>2. Understanding the</strong> <code>handler</code> <strong>Function and the role of AWSGI</strong></h5>
<p>The <code>handler</code> function is invoked every time the Lambda function receives a client request from the API Gateway.</p>
<p>The function takes the <code>event</code> argument that includes the request details in a <strong>JSON dictionary</strong> and passes it to the Flask application.</p>
<p><strong>AWSGI</strong> acts as an adapter, translating a Lambda event in JSON format into a WSGI request that a Flask application can understand, and converts the application’s response back into a JSON format that Lambda and API Gateway can process.</p>
<h5 id="heading-3-using-cache-storage"><strong>3. Using Cache Storage</strong></h5>
<p>The <code>get_redis_client</code> function is called once the <code>handler</code> function is called by the API Gateway. This allows the Flask application to store or fetch a cache from the Redis client:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> redis
<span class="hljs-keyword">import</span> redis.cluster
<span class="hljs-keyword">from</span> redis.cluster <span class="hljs-keyword">import</span> ClusterNode

_redis_client = <span class="hljs-literal">None</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_redis_client</span>():</span>
    <span class="hljs-keyword">global</span> _redis_client
    <span class="hljs-keyword">if</span> _redis_client <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
        REDIS_HOST = os.environ.get(<span class="hljs-string">"REDIS_HOST"</span>)
        REDIS_PORT = int(os.environ.get(<span class="hljs-string">"REDIS_PORT"</span>, <span class="hljs-number">6379</span>))
        REDIS_TLS = os.environ.get(<span class="hljs-string">"REDIS_TLS"</span>, <span class="hljs-string">"true"</span>).lower() == <span class="hljs-string">"true"</span>
        <span class="hljs-keyword">try</span>:
            startup_nodes = [ClusterNode(host=REDIS_HOST, port=REDIS_PORT)]
            _redis_client = redis.cluster.RedisCluster(
                startup_nodes=startup_nodes,
                decode_responses=<span class="hljs-literal">True</span>,
                skip_full_coverage_check=<span class="hljs-literal">True</span>,
                ssl=REDIS_TLS,                  <span class="hljs-comment"># elasticache has encryption in transit: enabled -&gt; must be true</span>
                ssl_cert_reqs=<span class="hljs-literal">None</span>,
                socket_connect_timeout=<span class="hljs-number">5</span>,
                socket_timeout=<span class="hljs-number">5</span>,
                health_check_interval=<span class="hljs-number">30</span>,
                retry_on_timeout=<span class="hljs-literal">True</span>,
                retry_on_error=[
                    redis.exceptions.ConnectionError,
                    redis.exceptions.TimeoutError
                ],
                max_connections=<span class="hljs-number">10</span>,            <span class="hljs-comment"># limit connections for Lambda</span>
                max_connections_per_node=<span class="hljs-number">2</span>     <span class="hljs-comment"># limit per node</span>
            )
            _redis_client.ping()
            main_logger.info(<span class="hljs-string">"successfully connected to ElastiCache Redis Cluster (Configuration Endpoint)"</span>)
        <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
            main_logger.error(<span class="hljs-string">f"an unexpected error occurred during Redis Cluster connection: <span class="hljs-subst">{e}</span>"</span>, exc_info=<span class="hljs-literal">True</span>)
            _redis_client = <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> _redis_client
</code></pre>
<h5 id="heading-4-handling-heavy-tasks-outside-of-the-handler-function"><strong>4. Handling Heavy Tasks Outside of the</strong> <code>handler</code> <strong>Function</strong></h5>
<p>Serverless functions can experience a <strong>cold start duration</strong>.</p>
<p>While a Lambda function can run for up to 15 minutes, its associated API Gateway has a timeout of 29 seconds (29,000 ms) for a RESTful API.</p>
<p>So, any heavy tasks like loading preprocessors, input data, or models should be performed once outside of the <code>handler</code> function, ensuring they are ready <em>before</em> the API endpoint is called.</p>
<p>Here are the loading functions called in <code>app.py</code>.</p>
<p><code>app.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> joblib

<span class="hljs-keyword">from</span> src._utils <span class="hljs-keyword">import</span> s3_load, s3_load_to_temp_file

preprocessor = <span class="hljs-literal">None</span>
X_test = <span class="hljs-literal">None</span>
model = <span class="hljs-literal">None</span>
backup_model = <span class="hljs-literal">None</span>


<span class="hljs-comment"># load processor</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_preprocessor</span>():</span>
    <span class="hljs-keyword">global</span> preprocessor
    preprocessor_tempfile_path = s3_load_to_temp_file(PREPROCESSOR_PATH)
    preprocessor = joblib.load(preprocessor_tempfile_path)
    os.remove(preprocessor_tempfile_path)


<span class="hljs-comment"># load input data</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_x_test</span>():</span>
    <span class="hljs-keyword">global</span> X_test
    x_test_io = s3_load(file_path=X_TEST_PATH)
    X_test = pd.read_parquet(x_test_io)


<span class="hljs-comment"># load model</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_model</span>():</span>
    <span class="hljs-keyword">global</span> model, backup_model
    <span class="hljs-comment"># try loading &amp; reconstructing the primary model</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># first load io file from the s3 bucket</span>
        model_data_bytes_io_ = s3_load(file_path=DFN_FILE_PATH)
        <span class="hljs-comment"># convert to checkpoint dictionary (containing hyperparameter set)</span>
        checkpoint_ = torch.load(
            model_data_bytes_io_, 
            weights_only=<span class="hljs-literal">False</span>, 
            map_location=device
        )
        <span class="hljs-comment"># reconstruct the model</span>
        model = t.scripts.load_model(checkpoint=checkpoint_, file_path=DFN_FILE_PATH)
        <span class="hljs-comment"># set the model evaluation mode</span>
        model.eval()

    <span class="hljs-comment"># else, backup model</span>
     <span class="hljs-keyword">except</span>:
        load_artifacts_backup_model()
</code></pre>
<h3 id="heading-step-4-publish-a-docker-image-to-ecr">Step 4: Publish a Docker Image to ECR</h3>
<p>After configuring the Flask application, we’ll containerize the entire application on <strong>Docker</strong>.</p>
<p>Containerization makes a package of the application, including models, its dependencies, and configuration in machine learning context, as a container<strong>.</strong></p>
<p>Docker creates a container image based on the instructions defined in a Dockerfile, and the Docker engine uses the image to run the isolated container.</p>
<p>In this project, we’ll upload the Docker container image to ECR, so the Lambda function can access it in production.</p>
<p>After this, we’ll define the <code>.dockerignore</code> file to optimize the container image:</p>
<p><code>.dockerignore</code></p>
<pre><code class="lang-plaintext"># any irrelevant data
__pycache__/
.ruff_cache/
.DS_Store/
.venv/
dist/
.vscode
*.psd
*.pdf
[a-f]*.log
tmp/
awscli-bundle/

# add any experimental models, unnecessary data
dfn_bayesian/
dfn_grid/
data/
notebooks/
</code></pre>
<p><code>Dockerfile</code></p>
<pre><code class="lang-dockerfile"><span class="hljs-comment"># serve from aws ecr </span>
<span class="hljs-keyword">FROM</span> public.ecr.aws/lambda/python:<span class="hljs-number">3.12</span>

<span class="hljs-comment"># define a working directory in the container</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>

<span class="hljs-comment"># copy the entire repository (except .dockerignore) into the container at /app</span>
<span class="hljs-keyword">COPY</span><span class="bash"> . /app/</span>

<span class="hljs-comment"># install dependencies defined in the requirements.txt</span>
<span class="hljs-keyword">RUN</span><span class="bash"> pip install --no-cache-dir -r requirements.txt</span>

<span class="hljs-comment"># define commands</span>
<span class="hljs-keyword">ENTRYPOINT</span><span class="bash"> [ <span class="hljs-string">"python"</span> ]</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [ <span class="hljs-string">"-m"</span>, <span class="hljs-string">"awslambdaric"</span>, <span class="hljs-string">"app.handler"</span> ]</span>
</code></pre>
<h4 id="heading-test-in-local">Test in Local</h4>
<p>Next, we’ll test the Docker image by building the container named <code>my-app</code> locally:</p>
<pre><code class="lang-bash"><span class="hljs-variable">$docker</span> build -t my-app -f Dockerfile .
</code></pre>
<p>Then, we’ll run the container with the <code>waitress</code> server in local:</p>
<pre><code class="lang-bash"><span class="hljs-variable">$docker</span> run -p 5002:5002 -e ENV=<span class="hljs-built_in">local</span> my-app app.py
</code></pre>
<p>The <code>-e ENV=local</code> flag sets the environment variable inside the container, which will trigger the <code>waitress.serve()</code> call in the <code>app.py</code>.</p>
<p>In the terminal, you’ll find a message saying the following:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1260/0*zu8mamgKMKOUxwCA.png" alt="Flask app response" width="600" height="400" loading="lazy"></p>
<p>You can also call the endpoint created to see the results returned:</p>
<pre><code class="lang-bash"><span class="hljs-variable">$uv</span> run app.py --cache-clear

<span class="hljs-variable">$curl</span> http://localhost:5002/v1/predict-price/{STOCKCODE}
</code></pre>
<h4 id="heading-publish-the-docker-image-to-ecr">Publish the Docker Image to ECR</h4>
<p>To publish the Docker image, we first need to configure the default AWS credentials and region:</p>
<ul>
<li><p>From the AWS account console, issue an access token and check the default region.</p>
</li>
<li><p>Store them in the <code>~/aws/credentials</code> and <code>~/aws/config</code> files:</p>
</li>
</ul>
<p><code>~/aws/credentials</code></p>
<pre><code class="lang-plaintext">[default] 
aws_secret_access_key=
aws_access_key_id=
</code></pre>
<p><code>~/aws/config</code></p>
<pre><code class="lang-plaintext">[default]
region=
</code></pre>
<p>After the configuration, we’ll publish the Docker image to ECR.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># authenticate the docker client to ECR</span>
<span class="hljs-variable">$aws</span> ecr get-login-password --region &lt;your-aws-region&gt; | docker login --username AWS --password-stdin &lt;your-aws-account-id&gt;.dkr.ecr.&lt;your-aws-region&gt;.amazonaws.com

<span class="hljs-comment"># create repository</span>
<span class="hljs-variable">$aws</span> ecr create-repository --repository-name &lt;your-repo-name&gt; --region &lt;your-aws-region&gt;

<span class="hljs-comment"># tag the docker image</span>
<span class="hljs-variable">$docker</span> tag &lt;your-repo-name&gt;:&lt;your-app-version&gt;  &lt;your-aws-account-id&gt;.dkr.ecr.&lt;your-aws-region&gt;.amazonaws.com/&lt;your-app-name&gt;:&lt;your-app-version&gt;

<span class="hljs-comment"># push</span>
<span class="hljs-variable">$docker</span> push &lt;your-aws-account-id&gt;.dkr.ecr.&lt;your-aws-region&gt;.amazonaws.com/&lt;your-repo-name&gt;:&lt;your-app-version&gt;
</code></pre>
<p>Here’s what’s going on:</p>
<ul>
<li><p><code>&lt;your-aws-region&gt;</code>: Your default AWS region (for example, <code>us-east-1</code> ).</p>
</li>
<li><p><code>&lt;your-aws-account-id&gt;</code>: 12-digit AWS account ID.</p>
</li>
<li><p><code>&lt;your-repo-name&gt;</code>: Your desired repository name.</p>
</li>
<li><p><code>&lt;your-app-version&gt;</code>: Your desired tag name (for example, <code>v1.0</code>).</p>
</li>
</ul>
<p>Now, the Docker image is stored in ECR with the tag:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1260/0*tUQkbDW-uAmrjBfx.png" alt="Fig. Screenshot of the AWS ECR console" width="600" height="400" loading="lazy"></p>
<p>Fig. Screenshot of the AWS ECR console</p>
<h3 id="heading-step-5-create-a-lambda-function">Step 5: Create a Lambda Function</h3>
<p>Next, we’ll create a Lambda function.</p>
<p>From the Lambda console, choose:</p>
<ul>
<li><p>The <code>Container Image</code> option,</p>
</li>
<li><p>The container image URL from the pull down list,</p>
</li>
<li><p>A function name of our choice, and</p>
</li>
<li><p>An architecture type (arm64 is recommended for a better price-performance).</p>
</li>
</ul>
<p><img src="https://miro.medium.com/v2/resize:fit:1260/0*3b-wIEUzRooQcvN_.png" alt="Fig. Screenshot of AWS Lambda function configurationFig. Screenshot of AWS Lambda function configuration" width="600" height="400" loading="lazy"></p>
<p>Fig. Screenshot of AWS Lambda function configuration</p>
<p>The Lambda function <code>my-app</code> was successfully launched.</p>
<h4 id="heading-connect-the-lambda-function-to-api-gateway">Connect the Lambda function to API Gateway</h4>
<p>Next, we’ll add API gateway as an event trigger to the Lambda function.</p>
<p>First, visit the API Gateway console and create <strong>REST API methods</strong> using the ARN of the Lambda function (press enter or click to view image in full size):</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1260/0*60TP64gdSjhKfiO8.png" alt="Fig. Screenshot of the AWS API Gateway configurationFig. Screenshot of the AWS API Gateway configuration" width="600" height="400" loading="lazy"></p>
<p>Fig. Screenshot of the AWS API Gateway configuration</p>
<p>Then, add resources to the created API gateway to create an endpoint:<br><code>API Gateway &gt; APIs &gt; Resources &gt; Create Resource</code></p>
<ul>
<li><p>Align the resource endpoint with the API endpoint defined in the <a target="_blank" href="http://app.py"><code>app.py</code></a>.</p>
</li>
<li><p>Configure CORS (for example, accept specific origins).</p>
</li>
<li><p>Deploy the resource to the stage.</p>
</li>
</ul>
<p>Going back to the Lambda console, you’ll find the API Gateway is connected as an event trigger:<br><code>Lambda &gt; Function &gt; my-app (your function name)</code></p>
<p><img src="https://miro.medium.com/v2/resize:fit:1260/0*DlfiEieZArmYlOuT.png" alt="Fig. Screenshot of the AWS Lambda dashboard" width="600" height="400" loading="lazy"></p>
<p>Fig. Screenshot of the AWS Lambda dashboard</p>
<h3 id="heading-step-6-configure-aws-resources">Step 6: Configure AWS Resources</h3>
<p>Lastly, we’ll configure the related AWS resources to make the system work in production.</p>
<p>This process involves the following steps:</p>
<h4 id="heading-1-the-iam-role-controls-who-to-access-resources">1. The IAM Role: Controls Who to Access Resources</h4>
<p>AWS requires <strong>IAM roles</strong> to grant temporary, secure permissions to users, mitigating security risks related to long-term credentials like passwords.</p>
<p>The IAM role leverages policies to grant accesses to the selected service. Policies can be issued by AWS or customized by the user by defining the inline policy.</p>
<p>It is important to avoid overly permissive access rights for the IAM role.</p>
<ol>
<li><p>In the Lambda function console, check the execution role:<br> <code>Lambda &gt; Function &gt; &lt;FUNCTION&gt; &gt; Permission &gt; The execution role</code>.</p>
</li>
<li><p>Set up the following policies to allow the Lambda’s IAM role to handle necessary operations:</p>
<ul>
<li><p><strong>Lambda</strong> <code>AWSLambdaExecute</code>: Allows executing the function.</p>
</li>
<li><p><strong>EC2</strong> <code>Inline policy</code>: Allows controlling the security group and the VPC of the Lambda function.</p>
</li>
<li><p><strong>ECR</strong> <code>AmazonElasticContainerRegistryPublicFullAccess</code> + <code>Inline policy</code>: Allows storing and pulling the Docker image.</p>
</li>
<li><p><strong>ElastiCache</strong> <code>AmazonElastiCacheFullAccess</code> + <code>Inline policy</code>: Allows storing and pulling caches.</p>
</li>
<li><p><strong>S3</strong>: <code>AmazonS3ReadOnlyAccess</code> + <code>Inline policy</code>: Allows reading and storing contents.</p>
</li>
</ul>
</li>
</ol>
<p>Now, the IAM role can access these resources and perfo the allowed actions.</p>
<h4 id="heading-2-the-security-group-controls-network-traffic">2. The Security Group: Controls Network Traffic</h4>
<p>A <strong>security group</strong> is a virtual firewall that controls inbound and outbound network traffic for AWS resources.</p>
<p>It uses stateful (allowing return traffic automatically) “allow-only” rules based on protocol, port, and IP address, where it denies all traffic by default.</p>
<p>Create a new security group for the Lambda function:<br><code>EC2 &gt; Security Groups &gt; &lt;YOUR SECURITY GROUP&gt;</code></p>
<p>Now, we’ll want to setup inbound / outbound traffic rules.</p>
<p>The inbound rules:</p>
<ul>
<li><p><strong>S3 → Lambda</strong>:<strong>Type</strong>*: HTTPS /* <strong>Protocol</strong>*: TCP /* <strong>Port range</strong>*: 443 / Source: Custom**</p>
</li>
<li><p><strong>ElastiCache → Lambda</strong>:<strong>Type</strong>*: Custom TCP /* <strong>Port range</strong>*: 6379 / Source: Custom**</p>
</li>
</ul>
<p>*Choose the created security group for the Lambda function as a custom source.</p>
<p>The outbound rules:</p>
<ul>
<li><p><strong>Lambda → Internet</strong>: <strong>Type</strong>*: HTTPS /* <strong>Protocol</strong>*: TCP /* <strong>Port range</strong>*: 443 /* <strong>Destination</strong>*: 0.0.0.0/0*</p>
</li>
<li><p><strong>ElastiCache → Internet</strong>: <strong>Type</strong>*: All Traffic /* <strong>Destination</strong>*: 0.0.0.0/0*</p>
</li>
</ul>
<h4 id="heading-3-the-virtual-private-cloud-vpc">3. The Virtual Private Cloud (VPC)</h4>
<p>A <strong>Virtual Private Cloud (VPC)</strong> provides a logically isolated private network for the AWS resources, acting as our own private data center within AWS.</p>
<p>AWS can create a <strong>Hyperplane ENI</strong> (Elastic Network Interface) for the Lambda function and its connected resources in the subnets of the VPC.</p>
<p>Though it’s optional, we’ll use the VPC to connect the Lambda function to the S3 storage and ElastiCache.</p>
<p>This process involves:</p>
<ol>
<li><p>Creating a VPC endpoint from the VPC console:<code>VPC &gt; Create VPC</code>.</p>
</li>
<li><p>Creating an STS (Security Token Service) endpoint:<br> <code>VPC &gt; PrivateLink and Lattice &gt; Endpoints &gt; Create Endpoint &gt;</code></p>
<ul>
<li><p><strong>Type</strong>*: AWS Service*</p>
</li>
<li><p><strong>Service name</strong>*: com.amazonaws.&lt;YOUR REGION&gt;.sts*</p>
</li>
<li><p><strong>Type</strong>*: Interface*</p>
</li>
<li><p><strong>VPC:</strong> Select the VPC created earlier.</p>
</li>
<li><p><strong>Subnets</strong>*: Select all subnets.*</p>
</li>
<li><p><strong>Security groups</strong>*: Select the security group of the Lambda function.*</p>
</li>
<li><p><strong>Policy</strong>*: Full access*</p>
</li>
<li><p><strong>Enable DNS names</strong></p>
</li>
</ul>
</li>
</ol>
<p>The VPC must have a dedicated endpoint for STS to receive temporary credentials from STS.</p>
<ol start="3">
<li><p>Create an S3 endpoint in the VPC:<br> <code>VPC &gt; PrivateLink and Lattice &gt; Endpoints &gt; Create Endpoint &gt;</code></p>
<ul>
<li><p><strong>Type</strong>*: AWS Service*</p>
</li>
<li><p><strong>Service name</strong>*: com.amazonaws.&lt;YOUR REGION&gt;.s3*</p>
</li>
<li><p><strong>Type</strong>*: Gateway*</p>
</li>
<li><p><strong>VPC:</strong> Select the VPC created earlier.</p>
</li>
<li><p><strong>Subnets</strong>*: Select all subnets.*</p>
</li>
<li><p><strong>Security groups</strong>*: Select the security group of the Lambda function.*</p>
</li>
<li><p><strong>Policy</strong>*: Full access*</p>
</li>
</ul>
</li>
</ol>
<p>Lastly, check the security group of the Lambda function and ensure that its VPC ID directs to the VPC created: <code>EC2 &gt; Security Group &gt; &lt;YOUR SECURITY GROUP FOR THE LAMDA FUNCTION&gt; &gt; VPC ID</code>.</p>
<p>That’s all for the deployment flow.</p>
<p>We can now test the API endpoint in production. Copy the <strong>Invoke URL</strong> of the deployed API endpoint: <code>API Gateway &gt; APIs &gt; Stages &gt; Invoke URL</code>. Then call the API endpoint and check if it responds predictions:</p>
<pre><code class="lang-bash"><span class="hljs-variable">$curl</span> -H <span class="hljs-string">'Authorization: Bearer YOUR_API_TOKEN'</span> -H <span class="hljs-string">'Accept: application/json'</span> \
     <span class="hljs-string">'&lt;INVOKE URL&gt;/&lt;ENDPOINT&gt;'</span>
</code></pre>
<p>For logging and debugging, we’ll use the LiveTail of CloudWatch: <code>CloudWatch &gt; LiveTail</code>.</p>
<h2 id="heading-building-a-client-application-optional">Building a Client Application (Optional)</h2>
<p>For full-stack deployment, we’ll build a simple React application to display the prediction using the <a target="_blank" href="https://recharts.org/en-US">recharts</a> library for visualization.</p>
<p>Other options for quick frontend deployment include <a target="_blank" href="https://streamlit.io/">Streamlit</a> or <a target="_blank" href="https://www.gradio.app/">Gradio</a>.</p>
<h3 id="heading-the-react-application">The React Application</h3>
<p>The React application creates a web page that fetches and visualizes sales predictions from an external API, recommending an optimal price point.</p>
<p>The app uses <code>useState</code> to manage its data and state, including the selected product, the list of sales predictions, and the loading/error status.</p>
<p>When the user initiates a request, a <code>useEffect</code> hook triggers a <code>fetch</code> request to a Flask backend. It handles the API response as a <strong>data stream</strong>, processing it line by line to progressively update the predictions.</p>
<p>The <code>AreaChart</code> from the <code>recharts</code> library then visualizes this data. The X-axis represents the <code>price</code> and the Y-axis represents the <code>sales</code>. The chart updates in real-time as the data streams in. Finally, the app displays the optimal price once all the predictions are received.</p>
<p><code>App.js</code>: (in a separate React app)</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ReferenceLine } <span class="hljs-keyword">from</span> <span class="hljs-string">'recharts'</span>


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// state</span>
  <span class="hljs-keyword">const</span> [predictions, setPredictions] = useState([])
  <span class="hljs-keyword">const</span> [start, setStart] = useState(<span class="hljs-literal">false</span>)
  <span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>)

  <span class="hljs-comment">// product data</span>
  <span class="hljs-keyword">let</span> selectedStockcode = <span class="hljs-string">'85123A'</span>
  <span class="hljs-keyword">let</span> selectedProduct = productOptions.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === selectedStockcode)[<span class="hljs-number">0</span>]

  <span class="hljs-comment">// api endpoint</span>
  <span class="hljs-keyword">const</span> flaskBackendUrl = <span class="hljs-string">"YOUR FLASK BACKEND URL"</span>

  <span class="hljs-comment">// create chart data to display</span>
  <span class="hljs-keyword">const</span> chartDataSales = predictions &amp;&amp; predictions.length &gt; <span class="hljs-number">0</span>
    ? predictions
      .map(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> ({
        <span class="hljs-attr">price</span>: item.unit_price,
        <span class="hljs-attr">sales</span>: item.predicted_sales,
        <span class="hljs-attr">volume</span>: item.unit_price !== <span class="hljs-number">0</span> ? item.predicted_sales / item.unit_price : <span class="hljs-number">0</span>
      }))
      .sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a.price - b.price)
    : [...selectedProduct[<span class="hljs-string">'histPrices'</span>]]

  <span class="hljs-comment">// optimal price to display</span>
  <span class="hljs-keyword">const</span> optimalPrice = predictions.length &gt; <span class="hljs-number">0</span>
    ? predictions.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> b.predicted_sales - a.predicted_sales)[<span class="hljs-number">0</span>][<span class="hljs-string">'unit_price'</span>]
    : <span class="hljs-number">0</span>

  <span class="hljs-comment">// fetch prediction results</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> handlePrediction = <span class="hljs-keyword">async</span> () =&gt; {
      setIsLoading(<span class="hljs-literal">true</span>)
      setPredictions([])
      <span class="hljs-keyword">const</span> errorPrices = selectedProduct[<span class="hljs-string">'errorPrices'</span>]

      <span class="hljs-keyword">await</span> fetch(flaskBackendUrl)
        .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
          <span class="hljs-keyword">if</span> (res.status !== <span class="hljs-number">200</span>) { setPredictions(errorPrices); setIsLoading(<span class="hljs-literal">false</span>); setStart(<span class="hljs-literal">false</span>) }
          <span class="hljs-keyword">else</span> <span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.resolve(res.clone().json())
        })
        .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
          <span class="hljs-keyword">if</span> (res &amp;&amp; res.length &gt; <span class="hljs-number">0</span>) setPredictions(res)
          <span class="hljs-keyword">else</span> setPredictions(errorPrices)
          setIsLoading(<span class="hljs-literal">false</span>); setStart(<span class="hljs-literal">false</span>)
        })
        .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> { setPredictions(errorPrices); setIsLoading(<span class="hljs-literal">false</span>); setStart(<span class="hljs-literal">false</span>) })
        .finally(setStart(<span class="hljs-literal">false</span>))
    }

    <span class="hljs-keyword">if</span> (start) handlePrediction()
    <span class="hljs-keyword">if</span> (predictions &amp;&amp; predictions.length &gt; <span class="hljs-number">0</span>) setStart(<span class="hljs-literal">false</span>)
  }, [flaskBackendUrl, start])


  <span class="hljs-comment">// render</span>
  <span class="hljs-keyword">if</span> (isLoading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Loading</span> /&gt;</span></span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ResponsiveContainer</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"100%"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"100%"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AreaChart</span>
          <span class="hljs-attr">key</span>=<span class="hljs-string">{chartDataSales.length}</span>
          <span class="hljs-attr">data</span>=<span class="hljs-string">{chartDataSales.sort(data</span> =&gt;</span> data.unit_price)}
          margin={{ top: 10, right: 30, left: 0, bottom: 0 }}
        &gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">CartesianGrid</span> <span class="hljs-attr">strokeDasharray</span>=<span class="hljs-string">"3 3"</span> <span class="hljs-attr">strokeOpacity</span>=<span class="hljs-string">{0.6}</span> /&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">XAxis</span>
            <span class="hljs-attr">dataKey</span>=<span class="hljs-string">"price"</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">value:</span> "<span class="hljs-attr">Unit</span> <span class="hljs-attr">Price</span> ($)", <span class="hljs-attr">position:</span> "<span class="hljs-attr">insideBottom</span>", <span class="hljs-attr">offset:</span> <span class="hljs-attr">0</span>, <span class="hljs-attr">fontSize:</span> <span class="hljs-attr">12</span>, <span class="hljs-attr">marginTop:</span> <span class="hljs-attr">10</span> }}
            <span class="hljs-attr">tickFormatter</span>=<span class="hljs-string">{(tick)</span> =&gt;</span> `$${parseFloat(tick).toFixed(2)}`}
            tick={{ fontSize: 12 }}
            padding={{ left: 20, right: 20 }}
          /&gt;

          <span class="hljs-tag">&lt;<span class="hljs-name">YAxis</span>
            <span class="hljs-attr">label</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">value:</span> "<span class="hljs-attr">Predicted</span> <span class="hljs-attr">Sales</span> ($)", <span class="hljs-attr">angle:</span> <span class="hljs-attr">-90</span>, <span class="hljs-attr">position:</span> "<span class="hljs-attr">insideLeft</span>", <span class="hljs-attr">fontSize:</span> <span class="hljs-attr">12</span> }}
            <span class="hljs-attr">tick</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">fontSize:</span> <span class="hljs-attr">12</span> }}
            <span class="hljs-attr">tickFormatter</span>=<span class="hljs-string">{(tick)</span> =&gt;</span> `$${tick.toLocaleString()}`}
          /&gt;

          {/* tooltips with the prediction result data */}
          <span class="hljs-tag">&lt;<span class="hljs-name">Tooltip</span>
            <span class="hljs-attr">contentStyle</span>=<span class="hljs-string">{{</span>
              <span class="hljs-attr">borderRadius:</span> '<span class="hljs-attr">8px</span>',
              <span class="hljs-attr">padding:</span> '<span class="hljs-attr">10px</span>',
              <span class="hljs-attr">boxShadow:</span> '<span class="hljs-attr">0px</span> <span class="hljs-attr">0px</span> <span class="hljs-attr">15px</span> <span class="hljs-attr">rgba</span>(<span class="hljs-attr">0</span>,<span class="hljs-attr">0</span>,<span class="hljs-attr">0</span>,<span class="hljs-attr">0.5</span>)'
            }}
            <span class="hljs-attr">formatter</span>=<span class="hljs-string">{(value,</span> <span class="hljs-attr">name</span>) =&gt;</span> {
              if (name === 'sales') {
                return [`$${value.toFixed(4)}`, 'Predicted Sales']
              }
              if (name === 'volume') {
                return [`${value.toFixed(0)}`, 'Volume']
              }
              return value
            }}
            labelFormatter={(label) =&gt; `Price: $${label.toFixed(2)}`}
          /&gt;

          {/* chart area = sales */}
          <span class="hljs-tag">&lt;<span class="hljs-name">Area</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"monotone"</span>
            <span class="hljs-attr">dataKey</span>=<span class="hljs-string">"sales"</span>
            <span class="hljs-attr">fillOpacity</span>=<span class="hljs-string">{1}</span>
            <span class="hljs-attr">fill</span>=<span class="hljs-string">"url(#colorSales)"</span>
          /&gt;</span>

          {/* vertical line for the optimal price */}
          {optimalPrice &amp;&amp;
            <span class="hljs-tag">&lt;<span class="hljs-name">ReferenceLine</span>
              <span class="hljs-attr">x</span>=<span class="hljs-string">{optimalPrice}</span>
              <span class="hljs-attr">strokeDasharray</span>=<span class="hljs-string">"4 4"</span>
              <span class="hljs-attr">ifOverflow</span>=<span class="hljs-string">"visible"</span>
              <span class="hljs-attr">label</span>=<span class="hljs-string">{{</span>
                <span class="hljs-attr">value:</span> `<span class="hljs-attr">Optimal</span> <span class="hljs-attr">Price:</span> $${<span class="hljs-attr">optimalPrice</span> !== <span class="hljs-string">null</span> &amp;&amp; <span class="hljs-attr">optimalPrice</span> &gt;</span> 0 ? Math.ceil(optimalPrice * 10000) / 10000 : ''}`,
                position: "right",
                fontSize: 12,
                offset: 10
              }}
            /&gt;
          }
        <span class="hljs-tag">&lt;/<span class="hljs-name">AreaChart</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ResponsiveContainer</span>&gt;</span>

      {optimalPrice &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Optimal Price: $ {Math.ceil(optimalPrice * 10000) / 10000}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<h2 id="heading-final-results">Final Results</h2>
<p>Now, the application is ready to serve.</p>
<p>You can explore the UI from <a target="_blank" href="https://kuriko-iwai.vercel.app/online-commerce-intelligence-hub">here</a>.</p>
<p>All code (backend) is available in <a target="_blank" href="https://github.com/krik8235/ml-sales-prediction">my Github Repo</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Building a machine learning system requires thoughtful project scoping and architecture design.</p>
<p>In this article, we built a dynamic pricing system as a simple single interface on containerized serverless architecture.</p>
<p>Moving forward, we’d need to consider potential drawbacks of this minimal architecture:</p>
<ul>
<li><p><strong>Increase in cold start duration</strong>: The WSGI adapter <code>awsgi</code> layer adds a small overhead. Loading a larger container image takes longer time.</p>
</li>
<li><p><strong>Monolithic function:</strong> Adding endpoints to the Lambda function can lead to a monolithic function where an issue in one endpoint impacts others.</p>
</li>
<li><p><strong>Less granular observability</strong>: AWS CloudWatch cannot provide individual invocation/error metrics per API endpoint without custom instrumentation.</p>
</li>
</ul>
<p>To scale the application effectively, extracting functionalities into a new microservice can be a good strategy to the next step.</p>
<p>I’m Kuriko IWAI, and you can find more of my work and learn more about me here:</p>
<p><a target="_blank" href="https://kuriko-iwai.vercel.app/"><strong>Portfolio</strong></a> <strong>/</strong> <a target="_blank" href="https://www.linkedin.com/in/k-i-i/"><strong>LinkedIn</strong></a> <strong>/</strong> <a target="_blank" href="https://github.com/krik8235"><strong>Github</strong></a></p>
<p><em>All images, unless otherwise noted, are by the author. This application utilizes synthetic dataset licensed under a Creative Commons Attribution 4.0 International (CC BY 4.0) license.</em></p>
<p><em>This information about AWS is current as of August 2025 and is subject to change.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn React in your Browser – freeCodeCamp Full Stack Curriculum Mid-2025 Update ]]>
                </title>
                <description>
                    <![CDATA[ Hey campers! The freeCodeCamp community is still very hard at work on the rest of the coursework for our full stack curriculum. It’s only been a few months, but already there are many campers going full-force through these new lessons and programming... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-react-in-your-browser-freecodecamp-full-stack-curriculum-mid-2025-update/</link>
                <guid isPermaLink="false">685049cc71faf4a81f93b409</guid>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Naomi Carrigan ]]>
                </dc:creator>
                <pubDate>Mon, 16 Jun 2025 16:43:56 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750092183369/0e6a0781-0913-4c28-9289-9af3831ebc67.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hey campers! The freeCodeCamp community is still very hard at work on the rest of the coursework for our <a target="_blank" href="https://www.freecodecamp.org/learn/full-stack-developer/">full stack curriculum</a>.</p>
<p>It’s only been a few months, but already there are many campers going full-force through these new lessons and programming challenges.</p>
<p>I’m excited to share our next wave of updates with you all.</p>
<h2 id="heading-new-curriculum-coursework">New Curriculum Coursework</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750152183453/6e973e4a-4b7e-4294-b056-95a5f6155e77.png" alt="6e973e4a-4b7e-4294-b056-95a5f6155e77" class="image--center mx-auto" width="717" height="766" loading="lazy"></p>
<p>We have just released three new sections of the curriculum: The React Hooks and State section, the Performance section, and the Testing section.</p>
<p>This new coursework includes:</p>
<ul>
<li><p>50 lecture videos</p>
</li>
<li><p>a dozen workshops and labs</p>
</li>
<li><p>three new review blocks</p>
</li>
<li><p>and a bunch of coursework to keep you on track with your learning goals (while we work to finish the remainder of the Full Stack curriculum.)</p>
</li>
</ul>
<p>Some of the projects you’ll build include:</p>
<ul>
<li><p>a fully playable Tic Tac Toe game</p>
</li>
<li><p>a color picker</p>
</li>
<li><p>and a superhero application form</p>
</li>
</ul>
<h2 id="heading-exams">Exams</h2>
<p>We know many of you are eagerly awaiting the release of the exams at the end of each module. These are nearly ready.</p>
<p>We’re also building our own custom exam environment that you can use to take these exams. This will strike a balance between respecting privacy and preserving academic integrity.</p>
<h2 id="heading-whats-next">What’s Next?</h2>
<p>The community is now focused on the CSS Libraries and TypeScript modules next. We’re also building Python modules.</p>
<p>We have a lot of stuff coming out in the next few months.</p>
<p>A super early sneak peek of some of the projects coming soon:</p>
<ul>
<li><p>build your own RPG character</p>
</li>
<li><p>a trading card game</p>
</li>
<li><p>a medical data validator</p>
</li>
<li><p>and more 🏕️</p>
</li>
</ul>
<h2 id="heading-get-involved">Get Involved</h2>
<p>Are you interested in helping bring our full stack curriculum to life? We have plenty of opportunities to contribute – you can see all of the <a target="_blank" href="https://github.com/freecodecamp/freecodecamp/issues">open issues on our GitHub repository</a>.</p>
<p>Start by reading our <a target="_blank" href="https://contribute.freecodecamp.org/intro/">contributor onboarding guide</a>. Then <a target="_blank" href="https://discord.gg/KVUmVXA">hop on over to our Discord community</a> with any questions you may have.</p>
<p>We’re stoked to watch you plow through all this new coursework. Keep up the forward momentum with your skills. Happy Coding! 💜</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What Makes Code Vulnerable – And How to Fix It ]]>
                </title>
                <description>
                    <![CDATA[ Writing code is relatively easy. But writing secure code is much harder. The truth is, most developers don’t realize their code is vulnerable until something breaks. Or, worse, until someone attacks it. So if you want secure code, you first have to k... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-makes-code-vulnerable-and-how-to-fix-it/</link>
                <guid isPermaLink="false">680679690b7357fefc92cf6b</guid>
                
                    <category>
                        <![CDATA[ #cybersecurity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vulnerability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Validation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Mon, 21 Apr 2025 16:59:21 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745251285687/7ce5aca0-1edc-49e4-879d-b5690cbb64ea.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Writing code is relatively easy. But writing secure code is much harder.</p>
<p>The truth is, most developers don’t realize their code is vulnerable until something breaks. Or, worse, until someone attacks it. So if you want secure code, you first have to know what bad code looks like.</p>
<p>In this tutorial, we’ll see 10 clear signs that your code might be vulnerable to attacks. And more importantly, how to fix it.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-hardcoded-credentials">1. Hardcoded Credentials</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-no-input-validation">2. No Input Validation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-poor-error-handling">3. Poor Error Handling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-outdated-dependencies">4. Outdated Dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-no-authentication-or-weak-authentication">5. No Authentication or Weak Authentication</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-missing-authorization-checks">6. Missing Authorization Checks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-7-exposed-sensitive-data-in-urls">7. Exposed Sensitive Data in URLs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-8-no-rate-limiting">8. No Rate Limiting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-9-unsafe-file-uploads">9. Unsafe File Uploads</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-10-missing-https">10. Missing HTTPS</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ul>
<h2 id="heading-1-hardcoded-credentials"><strong>1. Hardcoded Credentials</strong></h2>
<p>This one is <em>everywhere</em>. Maybe you’ve seen it yourself – an API key sitting right there in the code. A database password written in plain text.</p>
<p>It looks like this:</p>
<pre><code class="lang-plaintext">DB_PASSWORD = "supersecret123"
API_KEY = "sk_test_abc123"
</code></pre>
<p>If this code leaks (and it will), attackers can do whatever they want. They can log into your systems, steal your data, or run up huge bills on cloud services – all without breaking a sweat.</p>
<p>And here’s the scary part: this kind of leak doesn’t just happen when your whole project gets hacked. It can happen when someone pushes code to GitHub and forgets to add <code>.env</code> to <code>.gitignore</code>. Boom – your secret keys are now public.</p>
<h3 id="heading-how-to-protect-against-it"><strong>How to Protect Against It</strong></h3>
<p>Never hardcode sensitive data like API keys, database passwords, or tokens. Instead, use environment variables.</p>
<p>These are hidden from the source code and can be safely managed per environment (dev, test, production). For example, a <code>.env</code> file imported into your codebase:</p>
<pre><code class="lang-plaintext">import os
db_password = os.getenv("DB_PASSWORD")
</code></pre>
<h2 id="heading-2-no-input-validation"><strong>2. No Input Validation</strong></h2>
<p>If you trust user input, you’re already in trouble. Attackers love sending weird stuff, like super long strings, funky characters, or unexpected formats.</p>
<p>Here’s what it looks like:</p>
<pre><code class="lang-plaintext">username = request.GET['username']
print("Hello " + username)
</code></pre>
<p>Now someone enters:</p>
<pre><code class="lang-plaintext">username=Robert'); DROP TABLE users; --
</code></pre>
<p><strong>Boom.</strong> You’ve just been SQL injected. Your database table? Gone.</p>
<p>Without validation, your app can break or even be hijacked. Bad input can lead to issues like SQL injection, cross-site scripting (XSS), and general bugs.</p>
<p>Basically, you’re giving attackers a blank check.</p>
<h3 id="heading-how-to-protect-against-it-1"><strong>How to Protect Against It</strong></h3>
<p>Make sure you validate all inputs. For example:</p>
<pre><code class="lang-plaintext">import re
email = request.GET.get('email')
if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
    return "Invalid email format"
</code></pre>
<p>Use parameterized queries. Never build SQL strings from raw user input:</p>
<pre><code class="lang-plaintext">cursor.execute("SELECT * FROM users WHERE email = %s", (email,))
</code></pre>
<p>And use strict data types. Don’t just assume input is clean. Make it pass a test.Limit input length. No one needs a 5,000-character username.Escape special characters especially if you’re using input in HTML or SQL.</p>
<h2 id="heading-3-poor-error-handling"><strong>3. Poor Error Handling</strong></h2>
<p>This is what lazy error handling looks like:</p>
<pre><code class="lang-plaintext">except Exception as e:
    print(e)  # Exposes internal errors to the user
</code></pre>
<p>Or worse:</p>
<pre><code class="lang-plaintext">except:
    pass  # Silently swallows all errors
</code></pre>
<p>In the first example, the error is fully displayed to the user. The second example ignores all errors.</p>
<p>Silent errors are dangerous. And showing full error messages to users? That’s handing over a map to your system.</p>
<p>Imagine a database error pops up in production, and your app spits out something like:</p>
<pre><code class="lang-plaintext">psycopg2.OperationalError: could not connect to server: Connection refused
</code></pre>
<p>Great – now attackers know what database you’re using, and they might start poking around.</p>
<h3 id="heading-how-to-protect-against-it-2"><strong>How to Protect Against It</strong></h3>
<ul>
<li><p><strong>Log detailed errors</strong> – but do it securely. Use logging tools or services, and don’t store logs where users can see them.</p>
</li>
<li><p><strong>Show users simple messages</strong> like:<br>  <code>"Oops! Something went wrong. Please try again later."</code><br>  That’s all they need to know.</p>
</li>
<li><p><strong>Never expose stack traces in production.</strong> Turn off debug mode and use proper error pages.</p>
</li>
<li><p><strong>Handle specific exceptions</strong> where possible, so you know exactly what failed and why.</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-plaintext">try:
    process_data()
except ValueError as e:
    logger.error(f"Data error: {e}")
    return "Invalid input. Please check your data."
except Exception as e:
    logger.exception("Unexpected error")
    return "Something went wrong. Try again later."
</code></pre>
<p>Use error monitoring tools like Sentry, Rollbar, or LogRocket. They catch errors, track them, and help you fix them – before users even notice.</p>
<h2 id="heading-4-outdated-dependencies"><strong>4. Outdated Dependencies</strong></h2>
<p>Using old packages is like leaving your front door wide open. Attackers know exactly where the weak spots are – and they actively scan for them.</p>
<p>If your <code>package.json</code> or <code>requirements.txt</code> file hasn’t changed in years, that’s a red flag.</p>
<h3 id="heading-how-to-protect-against-it-3"><strong>How to Protect Against It</strong></h3>
<ul>
<li><p><strong>Update regularly.</strong> New versions often patch security flaws.</p>
</li>
<li><p><strong>Audit your dependencies.</strong> Use tools like <code>npm audit</code> and <code>pip-audit</code> based on your codebase.</p>
</li>
<li><p><strong>Automate updates</strong> with tools like Dependabot, Renovate, or PyUp.</p>
</li>
</ul>
<pre><code class="lang-plaintext">pip-audit
# or
npm audit
</code></pre>
<p>Even small packages can have big impacts. Stay updated, stay safe.</p>
<h2 id="heading-5-no-authentication-or-weak-authentication"><strong>5. No Authentication or Weak Authentication</strong></h2>
<p>If your app lets anyone in without verifying who they are, that’s game over. Weak logins are just as dangerous.</p>
<p>Common mistakes include:</p>
<ul>
<li><p><strong>No password complexity rules</strong> – Weak passwords like “123456” or “password” can be cracked in seconds using brute-force or dictionary attacks.</p>
</li>
<li><p><strong>Storing passwords in plain text</strong> – If your database is ever breached, all user credentials are exposed instantly, leading to massive data leaks and account takeovers.</p>
</li>
<li><p><strong>No account lockout after repeated failed logins</strong> – Without a limit on login attempts, attackers can keep guessing passwords endlessly using automated tools.</p>
</li>
</ul>
<h3 id="heading-how-to-protect-against-it-4"><strong>How to Protect Against It</strong></h3>
<p>First, you can hash passwords using strong algorithms like <code>bcrypt</code>.</p>
<p>Here’s an example in Python:</p>
<pre><code class="lang-plaintext">import bcrypt
hashed = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
</code></pre>
<p>You can also enforce strong password policies (min length, symbols, and so on) and use multi-factor authentication (MFA) if available for extra protection.</p>
<p>A few extra lines of code can stop a full-blown breach.</p>
<h2 id="heading-6-missing-authorization-checks"><strong>6. Missing Authorization Checks</strong></h2>
<p>Authentication checks <em>who you are</em>. Authorization checks <em>what you can do</em>. Skipping the second one is like giving everyone admin access.</p>
<p>Example:</p>
<pre><code class="lang-plaintext">@app.route('/user/&lt;id&gt;')
def get_user(id):
    return User.query.get(id)
</code></pre>
<p>Here, there’s no check to see if the current user is allowed to view that data.</p>
<h3 id="heading-how-to-protect-against-it-5"><strong>How to Protect Against It</strong></h3>
<pre><code class="lang-plaintext">@app.route('/user/&lt;id&gt;')
@login_required
def get_user(id):
    if current_user.id != int(id):
        return "Unauthorized", 403
    return User.query.get(id)
</code></pre>
<p>In the above code, a login is required and the user is verified before giving them access to the data.</p>
<ul>
<li><p>Always verify ownership and roles before showing or modifying data.</p>
</li>
<li><p>Implement access control rules across your API and frontend.</p>
</li>
<li><p>Don’t trust IDs from the frontend – verify on the backend too.</p>
</li>
</ul>
<h2 id="heading-7-exposed-sensitive-data-in-urls"><strong>7. Exposed Sensitive Data in URLs</strong></h2>
<p>Ever seen a password reset link like this?</p>
<pre><code class="lang-plaintext">https://example.com/reset-password?token=abcd1234
</code></pre>
<p>Looks harmless – but it’s not. Tokens, session IDs, and API keys <strong>should never be in URLs</strong>. They get saved in:</p>
<ul>
<li><p>Browser history</p>
</li>
<li><p>Server logs</p>
</li>
<li><p>Analytics tools</p>
</li>
</ul>
<h3 id="heading-how-to-protect-against-it-6"><strong>How to Protect Against It</strong></h3>
<p>Make sure you only send sensitive data in POST requests or headers, like this:</p>
<pre><code class="lang-plaintext">POST /reset-password
Authorization: Bearer abcd1234
</code></pre>
<h2 id="heading-8-no-rate-limiting"><strong>8. No Rate Limiting</strong></h2>
<p>Rate limiting is a security technique that controls how many times a user (or system) can make a request to your server within a given time frame – for example, no more than 10 login attempts per minute.</p>
<p>Without rate limits,</p>
<ul>
<li><p>An attacker can make 1,000 login attempts in a minute</p>
</li>
<li><p>Your server may crash under fake requests</p>
</li>
</ul>
<h3 id="heading-how-to-protect-against-it-7"><strong>How to Protect Against It</strong></h3>
<p>Set a max request limit per IP or user. You can use tools like Cloudflare or inbuilt tools in programming languages to do this. For example, in Python, we can use flask_limiter.</p>
<pre><code class="lang-plaintext">from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

limiter = Limiter(app, key_func=get_remote_address)

@app.route("/login")
@limiter.limit("5 per minute")
def login():
    # login logic
</code></pre>
<p>In the above code, the login attempts are limited to 5 per minute. Stop abuse before it starts.</p>
<h2 id="heading-9-unsafe-file-uploads"><strong>9. Unsafe File Uploads</strong></h2>
<p>Letting users upload files? Cool. But if you’re not careful, they can:</p>
<ul>
<li><p>Upload malware</p>
</li>
<li><p>Overwrite key files</p>
</li>
<li><p>Execute scripts on your server</p>
</li>
</ul>
<p>Here’s an example of a common mistake:</p>
<pre><code class="lang-plaintext">file. Save(f"/uploads/{file.filename}")
</code></pre>
<p>Any type of file could be uploaded this way.</p>
<h3 id="heading-how-to-protect-against-it-8"><strong>How to Protect Against It</strong></h3>
<p>To start, you can rename files before saving:</p>
<pre><code class="lang-plaintext">pythonCopyEditimport uuid
filename = str(uuid.uuid4()) + ".jpg"
</code></pre>
<p>You can check content type (not just file extension):</p>
<pre><code class="lang-plaintext">pythonCopyEditif file.content_type not in ["image/jpeg", "image/png"]:
    return "Invalid file type"
</code></pre>
<p>You also can store files outside public directory, and finally limit file size in your server config and backend code</p>
<h2 id="heading-10-missing-https"><strong>10. Missing HTTPS</strong></h2>
<p>If your app still uses plain old HTTP, all data travels in the open – including:</p>
<ul>
<li><p>Passwords</p>
</li>
<li><p>Tokens</p>
</li>
<li><p>Personal info</p>
</li>
</ul>
<p>Attackers can sniff it all with tools like <a target="_blank" href="https://www.freecodecamp.org/news/learn-wireshark-computer-networking/">Wireshark</a>.</p>
<h3 id="heading-how-to-protect-against-it-9"><strong>How to Protect Against It</strong></h3>
<p>To start, you can use HTTPS everywhere and get a free SSL cert from <a target="_blank" href="https://letsencrypt.org/">Let’s Encrypt</a>.</p>
<p>You can also redirect insecure traffic – here’s how you’d do it in Flask, for example:</p>
<pre><code class="lang-plaintext">@app.before_request
def before_request():
    if not request.is_secure:
        return redirect(request.url.replace("http://", "https://"))
</code></pre>
<p>Encrypting traffic is not optional – it’s table stakes for modern apps.</p>
<h2 id="heading-final-thoughts"><strong>Final Thoughts</strong></h2>
<p>Writing secure code isn’t about being perfect. It’s about being careful. Slow down. Look at your code with fresh eyes. Think like an attacker. Plan for failure before it happens.</p>
<p>The best security isn’t patched in later – it’s baked in from the start.</p>
<p>For more cybersecurity tutorials, <a target="_blank" href="https://newsletter.stealthsecurity.sh/">join my newsletter</a>. New to cybersecurity? Check out my <a target="_blank" href="https://start.stealthsecurity.sh/">Security Starter Course</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Git through Gamification – A Visual Guide to Key Version Control Concepts ]]>
                </title>
                <description>
                    <![CDATA[ Git has many concepts and commands that you’ll need to understand before you feel confident using it. Some of these concepts may sound trivial, especially to someone who has worked with Git before. But like most Git and coding concepts, even the “sim... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-git-through-gamification/</link>
                <guid isPermaLink="false">67c1cfa78df3594301bc3fef</guid>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gamification  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ version control ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jacob Stopak ]]>
                </dc:creator>
                <pubDate>Sun, 02 Mar 2025 06:00:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1740686401633/ffd9ac3c-668a-47bf-b2ba-f7cee14e74a8.webp" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Git has many concepts and commands that you’ll need to understand before you feel confident using it. Some of these concepts may sound trivial, especially to someone who has worked with Git before. But like most Git and coding concepts, even the “simple” ones tend to be abstract.</p>
<p>The three concepts that stand out to me as the most fundamental for being able to effectively work with Git at a basic level are:</p>
<ol>
<li><p>The <strong>working directory</strong></p>
</li>
<li><p>The <strong>staging area</strong></p>
</li>
<li><p>The <strong>commit history</strong></p>
</li>
</ol>
<p>In this article, we’ll take a new approach to representing these three concepts: by <em>visualizing them in an immersive, 3D game world!</em></p>
<p>I’ll provide a tangible, visual representation of these key Git concepts which are almost always described in an abstract and confusing way. I hope that this will make them much more intuitive for you to grasp.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-visualize-your-working-directory">Visualize your Working Directory</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-demystify-your-staging-area">Demystify your Staging Area</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-literally-walk-through-your-commit-history">Literally Walk through your Commit History</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-try-it-yourself">Try it Yourself</a></p>
</li>
</ol>
<h2 id="heading-visualize-your-working-directory">Visualize your Working Directory</h2>
<p>What does your brain picture when you think of the “working directory”? I assume it’s something like a folder structure starting at the project root, containing the code files and subfolders that make up the project.</p>
<p>While that is a fair description of the working directory, it is a bit hard to imagine and misses the segmentation that Git applies to your project. Although the current state of your entire project, folder structure, and code files do reside in the working directory, Git doesn’t really need to do much about that unless certain <em>changes</em> are detected in those files.</p>
<p>Git detects and reports changes to the working directory with the <a target="_blank" href="https://initialcommit.com/blog/git-status">Git status command</a>, which shows output like this:</p>
<pre><code class="lang-bash">Jack@RAPTOR ~/my-project (main)&gt; git status
On branch main
Your branch is up to date with <span class="hljs-string">'origin/main'</span>.

Changes not staged <span class="hljs-keyword">for</span> commit:
  (use <span class="hljs-string">"git add &lt;file&gt;..."</span> to update what will be committed)
  (use <span class="hljs-string">"git restore &lt;file&gt;..."</span> to discard changes <span class="hljs-keyword">in</span> working directory)
        modified:   main.py
        modified:   settings.py

Untracked files:
  (use <span class="hljs-string">"git add &lt;file&gt;..."</span> to include <span class="hljs-keyword">in</span> what will be committed)
        one.py
        three.py
        two.py

no changes added to commit (use <span class="hljs-string">"git add"</span> and/or <span class="hljs-string">"git commit -a"</span>)
</code></pre>
<p>The two relevant sections here are:</p>
<ol>
<li><p><strong>Changes not staged for commit:</strong> Lists existing files tracked by Git which currently contain code changes. In the example above, we see two “modified files”: <code>main.py</code> and <code>settings.py</code>.</p>
</li>
<li><p><strong>Untracked files:</strong> Lists new files in your project that Git doesn’t know about yet. In the example above, we see three new, untracked files: <code>one.py</code>, <code>two.py</code>, and <code>three.py</code>.</p>
</li>
</ol>
<p>When it comes to understanding Git, thinking of the working directory as the changes Git sees in these two sections – <strong>Untracked files</strong> and <strong>Modified files</strong> – is quite helpful.</p>
<p>But the <code>git status</code> command reports these details in the terminal in a purely text-based way, which doesn’t do newer Git users any favors when it comes to wrapping their heads around Git.</p>
<p>Some Git GUI’s do a better job with this (they do provide a safer point-and-click interface, after all), but in my experience, none of them make things <em>obvious at a glance</em>.</p>
<p>Instead, imagine that as a new Git user, you saw this:</p>
<p><a target="_blank" href="https://devlands.com"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740587730262/375bef09-b8b8-43e3-a18c-5b1e589b6097.png" alt="Image captured from Devlands, the gamified Git interface and tutorial, showing the untracked files and modified files sections of the working directory wall" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
<p>A nice big wall with clearly delineated sections for <strong>Untracked files</strong> and <strong>Modified files</strong>. Files corresponding to each section are represented as blocks on the wall within that section, clearly labelled with their filename.</p>
<p>More specifically, the blocks representing files <code>one.py</code>, <code>two.py</code>, and <code>three.py</code> are all sitting neatly in the <strong>Untracked files</strong> section, and the blocks representing the files <code>main.py</code> and <code>settings.py</code> are in the <strong>Modified files</strong> section.</p>
<p>This makes it abundantly clear to even a total novice that Git is interpreting these files differently and categorizing them in a logical way. It takes the abstract Git concept of the “working directory” and transforms it into a form that almost anyone can wrap their heads around at a glance.</p>
<p>But something is missing here. Let’s say you run the command <code>git add one.py</code>. This stages the untracked file <code>one.py</code> to be included in the next commit. What happens to the block labelled <code>one.py</code> on the wall?</p>
<h2 id="heading-demystify-your-staging-area">Demystify your Staging Area</h2>
<p>To answer that, let’s move on to the mysterious <a target="_blank" href="https://initialcommit.com/blog/git-add">Git “staging area”</a>. But first, where exactly IS the staging area?</p>
<p>Well, technically any staged file changes are still just sitting in the working directory, which makes things a bit confusing.</p>
<p>Here is how Git reports this in the terminal:</p>
<pre><code class="lang-bash">Jack@RAPTOR ~/D/git-worlds (main)&gt; git status
On branch main
Your branch is up to date with <span class="hljs-string">'origin/main'</span>.

Changes to be committed:
  (use <span class="hljs-string">"git restore --staged &lt;file&gt;..."</span> to unstage)
        new file:   one.py
</code></pre>
<p>As you can see from Git’s output, it now includes the section <strong>Changes to be committed</strong>, which includes the file <code>one.py</code> that was staged with the <code>git add</code> command.</p>
<p>But this is still a bit unclear. Are the staged file changes in <code>one.py</code> still a part of the working directory? Or does Git store them elsewhere?</p>
<p>Well, the answer is… BOTH:</p>
<p><a target="_blank" href="https://devlands.com"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740592262850/dc65c06d-0ec6-4de6-bbe9-53307d523e68.png" alt="Image captured from Devlands, the gamified Git interface and tutorial, adding the staged files section onto the working directory wall" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
<p>Here you can see that we zoomed out a bit from the previous image, to reveal a third section of the wall labeled <strong>Staged files</strong>.</p>
<p>Since we ran the command <code>git add one.py</code>, you can see that the corresponding block representing the <code>one.py</code> file moved from the Untracked files column to the Staged files column.</p>
<p>This conveys quite clearly that a file sitting in the staging area is still a part of the working directory (because it is a part of the overall wall), while also being segmented into its own designated space.</p>
<p>From a technical perspective, Git’s staging area is just a file named <strong>index</strong> which lives in the <code>.git/</code> folder. Git builds up the code changes specified by the <code>git add</code> command in this file, which is used as the source for those changes the next time the <code>git commit</code> command is run.</p>
<p>But from a workflow perspective, representing the staging area as a section on the “working directory wall” as in the image above makes things more intuitive to understand.</p>
<p>Next, let’s explore how we might visualize things once the staged changes are turned into a new Git commit and become a part of the active branch.</p>
<h2 id="heading-literally-walk-through-your-commit-history">Literally Walk through your Commit History</h2>
<p>What does your mind’s eye see when you think of Git’s “commit history”?</p>
<p>Well, the prettiest way Git does it in the terminal is by using the <a target="_blank" href="https://initialcommit.com/blog/git-log">Git log command</a>, such as <code>git log --graph --all</code>, which provides output like:</p>
<pre><code class="lang-bash">* commit 88085cff3e2d7657f26eb6479b308526df7d2bba (HEAD -&gt; dev, origin/dev)
| Author: Jacob Stopak &lt;jacob@initialcommit.io&gt;
| Date:   Tue Apr 23 20:31:24 2024 -0700
|
|     Fix <span class="hljs-built_in">command</span> as title clip, ellipses and arrow length <span class="hljs-keyword">in</span> rebase subcommand
|
|     Signed-off-by: Jacob Stopak &lt;jacob@initialcommit.io&gt;
|
*   commit e264605ea26a808c34d4dc2fbc6dad65a8e28c5f
|\  Merge: cb3fa5f b8c071c
| | Author: Jacob Stopak &lt;jacob@initialcommit.io&gt;
| | Date:   Wed Mar 20 19:51:06 2024 -0700
| |
| |     Merge branch <span class="hljs-string">'main'</span> into dev
| |
* | commit cb3fa5f3bdbdcff3d9a8c844cda99d46bf64e337
| | Author: Jacob Stopak &lt;jacob@initialcommit.io&gt;
| | Date:   Sat Mar 9 22:00:49 2024 -0800
| |
| |     Add --staged flag to git restore subcommand
| |
| |     Signed-off-by: Jacob Stopak &lt;jacob@initialcommit.io&gt;
| |
| * commit b8c071cb9a1653748525aa01c2b6bafe06ed9100
|/  Author: Jacob Stopak &lt;jacob@initialcommit.io&gt;
|   Date:   Wed Mar 20 19:50:53 2024 -0700
|
|       Correct license specified <span class="hljs-keyword">in</span> pyproject.toml from MIT to GNU GPLv2
|
|       Signed-off-by: Jacob Stopak &lt;jacob@initialcommit.io&gt;
|
* commit 32a3a3fca583f6c68225b974716e74b557a1a094
| Author: Jacob Stopak &lt;49353917+initialcommit-io@users.noreply.github.com&gt;
| Date:   Tue Aug 22 11:31:38 2023 -0700
|
|     Update README.md
</code></pre>
<p>Unfortunately, this is not so pretty at all. This long, garbled list of commit IDs, names, dates, and commit messages is definitely not something most folks would consider user-friendly.</p>
<p>The <code>--graph</code> option supplied above does show the commit relationships by drawing little lines connecting each commit in the terminal, but the purely text-based nature of this is just not intuitive to most people at a glance.</p>
<p>Now consider the following gamified representation of Git’s commit history:</p>
<p><a target="_blank" href="https://devlands.com"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740594184258/8d5a33c8-ad60-4496-a50d-a27fc6b8e752.png" alt="Image captured from Devlands, the gamified Git interface and tutorial, showing the project's commit history and branches" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
<p>Now we’re talkin’! In this image, each Git commit is represented by a white block with a shortened 6-character commit ID.</p>
<p>Each white commit block points back to its parent commit with an arrow, forming very clear chains of commits that make up Git branches.</p>
<p>You might have noticed that some of the white commit blocks have colored blocks sitting on top of them. The green blocks are <a target="_blank" href="https://initialcommit.com/blog/git-branches">branch names</a>, the yellow blocks are <a target="_blank" href="https://initialcommit.com/blog/git-tag">Git tags</a>, the blue block is <a target="_blank" href="https://initialcommit.com/blog/what-is-git-head">Git’s HEAD pointer</a>, and the red blocks are remote-tracking branches. These are collectively referred to as <a target="_blank" href="https://initialcommit.com/blog/what-is-git-head#git-refs-and-heads">Git refs</a>.</p>
<p>Besides being able to easily distinguish between them, representing ref types as different colored blocks clarifies another often-confusing Git concept. In Git, branches (along with other refs types) are just “pointers” to a specific commit. It is tempting to think of a branch as a series of connected commits that share a history – and conceptually this is correct – but in Git, a branch is really just a glorified label pointing to a specific commit.</p>
<p>In this gamified world, you can <em>literally walk through your commit history</em> to see, interact with, and examine the code changes in any commit.</p>
<h2 id="heading-summary">Summary</h2>
<p>In this article, we explored how Git’s fundamental concepts - the working directory, staging area, and commit history - can be difficult to grasp due to their abstract nature.</p>
<p>To make these concepts more accessible, we introduced a gamified, visual approach that transforms them into something tangible: an immersive game world where files and commits are represented as interactive blocks.</p>
<p>By presenting Git this way, beginner coders, students, and developers of all experience levels can intuitively learn Git concepts and commands, and confidently apply them in professional projects.</p>
<h2 id="heading-try-it-yourself">Try it Yourself</h2>
<p>The images in this post were captured in <a target="_blank" href="https://devlands.com">Devlands</a>, the first and only <em>gamified Git interface and tutorial</em>, which I’m building in Python.</p>
<p>In Devlands, not only can you walk through your codebase… You can also learn Git concepts and commands with a character-guided tutorial, simulate and run Git commands directly in the game, see their results applied in the game world in real time, and use AI to explain code you don’t understand.</p>
<p>If you or someone you know is a visual learner, beginner coder, or newer Git user, <a target="_blank" href="https://devlands.com">consider checking it out!</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Help Someone with Their Code Using the Socratic Method ]]>
                </title>
                <description>
                    <![CDATA[ As a programming community, freeCodeCamp helps many people who have questions about their code. It can be quite tempting to simply provide the learner with the answer and move on, but that’s actually detrimental to the learning process. Here’s why: W... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-help-someone-with-their-code-using-the-socratic-method/</link>
                <guid isPermaLink="false">677d816db702998ae550cebf</guid>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Naomi Carrigan ]]>
                </dc:creator>
                <pubDate>Tue, 07 Jan 2025 19:33:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/2RRq1BHPq4E/upload/904ec5e77783268f025191b07da29f08.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a programming community, freeCodeCamp helps many people who have questions about their code. It can be quite tempting to simply provide the learner with the answer and move on, but that’s actually detrimental to the learning process. Here’s why:</p>
<p>When you give someone the answer, you are depriving them of that “aha” moment. You are removing the opportunity for them to learn how to reach the conclusion through their own thinking, and instead allowing them to progress with minimal effort or thought.</p>
<p>So how can you best help someone with their code?</p>
<h2 id="heading-what-is-the-socratic-method">What is the Socratic Method?</h2>
<p>The Greek philosopher Plato was a student of another philosopher, Socrates. In Plato’s works, he often writes about the debates that Socrates would have with his colleagues and students.</p>
<p>Socrates would begin these discussions by raising common beliefs and scrutinizing them to question their compatibility with other beliefs, and guide people to reach the truth.</p>
<p>But how does that translate to our modern day interactions in a digital age?</p>
<p>Let’s consider a real example from one of our communities:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736179977371/7e087ee9-4b7e-4321-ade9-18019289320d.png" alt="A Discord message from the user Razzle Dazzle, reading &quot;How do I find the sum of the numbers in an array?&quot;" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You might be tempted to give them the direct answer, such as this code example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> sum = nums.reduce(<span class="hljs-function">(<span class="hljs-params">acc, el</span>) =&gt;</span> acc + el, <span class="hljs-number">0</span>);
</code></pre>
<p>But in doing so, you have performed the logical reasoning on behalf of the learner.</p>
<p>Instead, you should focus on asking pointed questions to <em>guide</em> them to the answer. For example, you might start by asking:</p>
<blockquote>
<p>❓ How would you find the sum of a list of numbers on pen and paper, without code?</p>
</blockquote>
<p>It may seem counter-intuitive to ask the learner a question that requires them to step away from the code, but you are actually pointing them to the underlying logic behind their question.</p>
<p>Let’s assume the learner responds with something like:</p>
<blockquote>
<p>I would go through each number, one by one, and add it to the sum of the previous numbers.</p>
</blockquote>
<p>As the learner begins answering your questions, the dialogue should progress in this call-and-response format. Your questions should become increasingly narrow and pointed with the learner’s progress toward the solution.</p>
<p>For example, a series of questions might look like:</p>
<blockquote>
<p>Instructor: “Great, now what is an array of numbers?”<br>Student: “A list?”<br>Instructor: “Good! How would you iterate through that list?”<br>Student: “With a for loop.”<br>Instructor: “And what does your loop need to do on each iteration?”<br>Student: “Add the current number to the sum.”<br>Instructor: “Where can you find the sum?”<br>Student: “I could put it in a variable outside the loop.”<br>Instructor: “Great, now you’re ready to try writing the code.”<br>— original example written for this article</p>
</blockquote>
<p>At this point, the learner will likely connect the dots and reach the final solution.</p>
<h2 id="heading-socrates-in-modern-culture">Socrates in Modern Culture</h2>
<p>Learning the Socratic method is hard. In fact, many do not encounter it until they reach their university studies. But there are examples found in modern pop culture that can help you understand how the Socratic method works.</p>
<p>The TV show House, M.D. is rife with examples. Take this exchange from the episode titled “Three Stories”:</p>
<blockquote>
<p>House: “Kidney stones would cause what?”<br>Student: “Blood in urine.”<br>House: “What colour is your pee?”<br>Student: “Yellow.”<br>House: “What colour is your blood?”<br>Student: “Red.”<br>House: “What colours did I use?”<br>Student: “Red, yellow, and brown.<br>House: “And brown. What causes brown?”<br>Student: “Waste”.<br>— (Frapier, 2008)¹</p>
</blockquote>
<p>You’ll notice how this exchange took place. House’s goal here was not to <em>give</em> the learner the answer, but to ask deductive questions to <em>guide</em> the learner to reach the answer on their own.</p>
<p>Consider the popular movie The Matrix:</p>
<blockquote>
<p>Morpheus: “Have you ever had a dream, Neo, that you were so sure was real?”<br>Neo: “This can't be…”<br>Morpheus: “Be what? Be real?”<br>Morpheus: “What if you were unable to wake from that dream, Neo? How would you know the difference between the dreamworld and the real world?”<br>— (Wachowski &amp; Wachowski, 1999)²</p>
</blockquote>
<p>In this scene, Morpheus is applying the Socratic method to lead Neo to question his perceptions of reality. This is a rather dramatic example, but the premise remains the same: rather than telling the learner how they should think, you guide them to reach the conclusion through their own volition.</p>
<p>Finally, let’s look at an example from Legally Blonde:</p>
<blockquote>
<p>Elle: “Your father was shot while you were in the shower?”<br>…<br>Chutney: “Yes. I was washing my hair.”<br>Elle: “Miss Windham, can you tell us what you'd been doing earlier in the day?”<br>Chutney: “I got up, went to Starbucks, went to the gym, got a perm, and came home.”<br>Elle: “Where you got in the shower.”<br>Chutney: “Yes.”<br>…<br>Elle: “…Had you ever gotten a perm before, Miss Windham?”<br>Chutney: “Yes.”<br>Elle: “How many, would you say?”<br>Chutney: “Two a year since I was twelve. You do the math.”<br>…<br>Elle: “Chutney, why is it that Tracy Marcinko's curls were ruined when she got hosed down?”<br>Chutney: “Because they got wet.”<br>Elle: “That's right. Because isn't the first cardinal rule of perm maintenance that you are forbidden to wet your hair for at least twenty-four hours after getting a perm at the risk of de-activating the ammonium thiglycolate? And wouldn't someone who's had -- thirty perms ? -- throughout her lifetime, be well aware of this rule? And if you, in fact, were not washing your hair, as I suspect you were not, since your curls are still intact, wouldn't you have heard the gunshot?”<br>—(Luketic, 2001)³</p>
</blockquote>
<p>The Socratic method can often be seen in law, and this serves as an excellent example. Through this exchange, Elle is not trying to guide Chutney to reach a conclusion, but rather the <em>spectators</em> (in this case, the jury). This is an important distinction for a community such as ours: where engaging in a Socratic discussion with one member can actually benefit current and future members who may observe or revisit your conversation.</p>
<h2 id="heading-goal-of-the-socratic-method">Goal of the Socratic Method</h2>
<p>It is important to recognize that the goal of the Socratic method is <em>not</em> to present a quick exchange of information. Instead, the aim is to first get the learner to realize that they know less than they believe they do, then guide them to the answer through questions that elicit certain thought processes.⁴</p>
<p>When applying this to learning programming, then, it’s important to remember the phrase “challenge your assumptions”. We often assume that we know what the code we have written is doing, so our first step when it is not working is to examine those assumptions.</p>
<p>As we guide learners through the process of debugging, we want to ask questions that do the same. A common question in your repertoire should be “What does this line of code do?”. When the learner answers with information that is inaccurate, respond with questions that drill down into smaller components of the code – break the problem into pieces, per se.</p>
<p>Consider this example:</p>
<blockquote>
<p>Learner: “but maybe that wouldnt work because I need to find the book not the id in the book”<br>Instructor: “Correct. Now, the good news is that we have a function that would ostensibly do that. The bad news is that function doesn't do that. What does that function do instead?”<br>Learner: “returns bookId”<br>— sourced from our Discord community⁵</p>
</blockquote>
<p>By asking the question “What does that function do instead?”, the instructor has provided the direction for the learner to reach the correct conclusion without having to provide any specific information. The learner already knew that the function did not perform as expected, and the instructor asked the question to challenge the learner’s assumption that the function <em>did</em> perform.</p>
<p>Here’s another example:</p>
<blockquote>
<p>Instructor: “This is the example from the Chalenge (sic). Did you follow that example they gave?”<br>Learner: “yes but i didnt understand the for-in loop, i didnt understand "(const food in refigerator)", having to state the string property name with const or let was confusing (it isnt anymore)”<br>Instructor: “Ok, so lets start here instead of the full solution to the Challenge”<br>Instructor: “What does that code do when you run it?”<br>…<br>Learner: “each of the object's keys were set to the variable food which was made in the for-in loop, it then iterates through the object and logs the key and value assigned to the key?”<br>— sourced from our Discord community⁶</p>
</blockquote>
<p>Again we can see how the instructor focuses on asking pointed questions that guide the user toward the solutions <em>through their own reasoning</em>.</p>
<blockquote>
<p>❗ That is the ultimate goal of the Socratic method: to guide the learner to reach the logical conclusion solely through their own reasoning.</p>
</blockquote>
<h2 id="heading-long-term-benefits-of-the-socratic-method">Long-Term Benefits of the Socratic Method</h2>
<p>The Socratic method is not solely beneficial for resolving the immediate solution. The deductive reasoning process that is applied in this approach can also serve the learner well over the long-term.</p>
<p>The process of asking a learner questions to challenge their assumptions and knowledge, and guide them to the solution, is something that can be internalized as well. It’s a powerful tool to have in your repertoire for approaching debugging, isolating assumptions, and even learning to articulate an issue.</p>
<p>That is, by walking a learner through this call-and-response conversation, the learner can also walk away with the ability to ask <em>themselves</em> these questions. They can take the same process of asking increasingly narrowing questions as a logical pathway and run through it mentally when they encounter future issues with their code (or even in other aspects of life)!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Providing a solution directly to a learner inhibits their intellectual growth and deprives them of the rewarding experience that comes from reaching their own logical conclusion. By leveraging techniques like the Socratic method, we can foster a stronger and more effective educational environment that allows learners to grow and thrive.</p>
<blockquote>
<p>💡 If you were sent this article in response to a forum post, Reddit comment, Discord message, or other communication where you gave a fellow learner a working solution, please consider the merits of this method instead.</p>
</blockquote>
<p>This approach can seem tedious and lengthy, and at times it is. It is far quicker (and arguably easier) to hand someone the code that resolves their problem.</p>
<p>But that approach, more often than not, harms the learner in the end. And, if you’ll forgive this author for an anecdote, I have seen people get frustrated when they are the subject of a Socratic approach, or lose patience with the back and forth conversation. But I have <em>never</em> seen them upset with or disappointed by that end result – the “aha” moment where they deduce the solution to the problem through their own reasoning.</p>
<h3 id="heading-sources">Sources:</h3>
<ol>
<li><p>¹ Frapier, M. (2008). Being Nice is Overrated: House and Socrates on the Necessity of Conflict. In <em>House and Philosophy</em> (pp. 100–101). John Wiley &amp; Sons, Inc.</p>
</li>
<li><p>² Wachowski, L., &amp; Wachowski, L. (Directors). (1999, March 24). <em>The Matrix</em> (Z. Staenberg, Ed.). Warner Bros.</p>
</li>
<li><p>³ Luketic, R. (Director). (2001, July 13). <em>Legally Blonde</em> (A. Brandt-Burgoyne, Ed.). MGM Distribution Co.</p>
</li>
<li><p>⁴ Frapier, M. (2008). Being Nice is Overrated: House and Socrates on the Necessity of Conflict. In <em>House and Philosophy</em> (p. 103). John Wiley &amp; Sons, Inc.</p>
</li>
<li><p>⁵ lightskingeneral &amp; plamoni (2024, January 4). [Discord conversation]. Discord. Retrieved 2025, January 6, from <a target="_blank" href="https://discord.com/channels/692816967895220344/718214639669870683/1192488621043888198">https://discord.com/channels/692816967895220344/718214639669870683/1192488621043888198</a></p>
</li>
<li><p>⁶ lightskingeneral &amp; jeremylt (2023, November 13). [Discord conversation]. Discord. Retrieved 2025, January 6, from <a target="_blank" href="https://discord.com/channels/692816967895220344/718214639669870683/1173733715109761065">https://discord.com/channels/692816967895220344/718214639669870683/1173733715109761065</a></p>
</li>
</ol>
<p>Special thanks to ArielLeslie and JeremyLT for their help with this article.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Make Learning to Code Easier by Focusing on the Fundamentals ]]>
                </title>
                <description>
                    <![CDATA[ It’s the beginning of the year again, and perhaps you’re still struggling to learn that programming language. We’ve all been there. Let me share a story from my own journey. In 2016, I thought I wasn’t cut out for programming. After months of trying ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-learning-to-code-easier-by-focusing-on-the-fundamentals/</link>
                <guid isPermaLink="false">6776aff4291cde01e8a6dff0</guid>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Tips ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Spruce Emmanuel ]]>
                </dc:creator>
                <pubDate>Thu, 02 Jan 2025 15:25:40 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735830905235/898a0c35-3f2a-4a05-86e8-866bb99eda42.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>It’s the beginning of the year again, and perhaps you’re still struggling to learn that programming language. We’ve all been there. Let me share a story from my own journey.</p>
<p>In 2016, I thought I wasn’t cut out for programming. After months of trying and failing with my first language, I came to a conclusion: I wasn’t smart enough. I thought some people were naturally gifted, while others, like me, simply weren’t meant for programming.</p>
<p>I gave up several times, convinced I didn’t have the talent needed to succeed.</p>
<p>Fast forward to today eight years later. I’ve become proficient in several programming languages. Looking back, I realize programming doesn’t come naturally to anyone. The difference between those who seem “gifted” and those of us who struggled is simple: it’s all about having the right foundational knowledge.</p>
<p>Programming is like walking into a movie halfway through you can’t understand what’s happening because you missed the beginning. The same applies to programming. You can’t build an advanced calculator app without understanding basic data types or algorithms.</p>
<p>Here’s the truth: programming isn’t inherently difficult. Most beginners struggle because they skip key foundational steps. Without these prerequisites, programming can feel like trying to swim in the deep end without first learning how to float.</p>
<p>But don’t worry I’ve got you covered. By the end of this article, you’ll know exactly what these prerequisites are, how to develop them, and why they’re the key to making programming click for you.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-why-programming-feels-hard-hint-its-not-about-talent">Why Programming Feels Hard – Hint: It’s Not About Talent</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-prerequisites-you-actually-need">The Prerequisites You Actually Need</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-data-structures-taking-user-input">Data Structures: Taking User Input</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-algorithms-performing-computations">Algorithms: Performing Computations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-programming-languages-displaying-the-output">Programming Languages: Displaying the Output</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-additional-skills">Additional Skills</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-the-right-foundations-practice-practice-practice">How to Build the Right Foundations: Practice, Practice, Practice</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ol>
<h2 id="heading-why-programming-feels-hard-hint-its-not-about-talent">Why Programming Feels Hard – Hint: It’s Not About Talent</h2>
<p>Let me pick up my story again. By 2018, I was becoming a confident developer. I could build basic websites, fetch data from a database using APIs, and display it on the screen. I thought I had programming figured out.</p>
<p>Then came my first job interview.</p>
<p>During the interview, I was asked a seemingly simple question: <em>“What happens when you type</em> <em>www.google.com</em> <em>into the address bar and press Enter? You have 30 minutes.”</em></p>
<p>I paused, thought for a moment, and gave my best answer. I spoke for maybe five minutes, then the interview ended.</p>
<p>Later, I Googled the question out of curiosity. What I found shocked me. The question wasn’t just about typing and entering a URL, it was about networks, servers, DNS lookups, HTTP requests, rendering engines, and more. That’s when it hit me: I had barely scratched the surface. There was so much foundational knowledge I was missing.</p>
<p>That day, I realized programming isn’t just about fetching data from a database or making a website look good. It’s about understanding the layers beneath the surface. If you're curious, I didn’t get the job. In fact, I never heard back from them. Honestly, I wouldn’t have hired me either.</p>
<p>Now, think about that interview question: Could you confidently explain what happens when you hit “Enter” on www.google.com?</p>
<p>If you’re like I was back then, probably not. But here’s the good news: If I were asked that same question today, I could speak on it for an hour. Heck, I could even write a 1,000-word article about it.</p>
<h3 id="heading-the-real-problem-isnt-talent">The Real Problem Isn’t Talent</h3>
<p>Here’s the key takeaway: programming success isn’t about talent or intelligence. If you try to learn programming without the right preparation, you’ll keep hitting a wall of frustration.</p>
<p>So, no—it’s not talent you lack. It’s preparation. And the good news? Lack of preparation is something you can fix.</p>
<h2 id="heading-the-prerequisites-you-actually-need"><strong>The Prerequisites You Actually Need</strong></h2>
<p>To understand the prerequisites, let’s take a step back and consider what a computer is actually for. At its core, the main purpose of a computer is to:</p>
<ol>
<li><p><strong>Take user input</strong>,</p>
</li>
<li><p><strong>Perform computations</strong>, and</p>
</li>
<li><p><strong>Display the output</strong>.</p>
</li>
</ol>
<p>Every piece of software or program ever developed revolves around these three tasks. As a programmer, your role is to create software that performs these functions properly.</p>
<p>To do this, you need to build your skills in a way that aligns with these tasks. This means learning about data structures and algorithms, and then diving into a programming language. Let’s dig into each of these skills more deeply.</p>
<h2 id="heading-data-structures-taking-user-input"><strong>Data Structures: Taking User Input</strong></h2>
<p>So, users interact with your software, whether they’re clicking buttons, filling out forms, or uploading files. And guess what? All that interaction creates data that you, the developer, need to manage. But how do you do that without going crazy? That’s where <strong>data structures</strong> come in.</p>
<h3 id="heading-what-are-data-structures"><strong>What Are Data Structures?</strong></h3>
<p>Think of data structures like special containers for your data. But not just any containers – they’re the kind that let you quickly grab, change, and organize your data in the most efficient way possible. Without them, managing user input would be like trying to store your clothes in a messy pile rather than a neat closet. Not fun, right?</p>
<h3 id="heading-a-few-data-structures-you-should-know"><strong>A Few Data Structures You Should Know</strong></h3>
<p>There are tons of data structures out there, but let’s talk about a couple that are absolute essentials:</p>
<p><strong>1. Arrays</strong></p>
<p>Arrays are like simple, ordered lists. Imagine a row of boxes, each labeled with a number (index). You can put something in each box, and when you want to grab something, you just tell the system the number of the box. Super easy! It’s like a list of your favorite songs, where each song is numbered in order.</p>
<p><strong>2. Hash Tables (or Dictionaries)</strong></p>
<p>Hash tables are the cool kids of the data structure world. Instead of organizing data by number, they let you organize it by keys, which are like labels that help you find things super fast. If you had a list of customers, you could use their customer IDs as the “key” to look up their info. Think of it like a phone book—rather than flipping through pages, you jump straight to the person’s name based on how the names are organized (likely alphabetically).</p>
<h3 id="heading-why-should-you-care-about-data-structures"><strong>Why Should You Care About Data Structures?</strong></h3>
<p>Good question! Here’s the deal: first of all, data structures help you organize your data in an intelligent way that makes sense. They keep things neat and make them easy to access. No more digging through a pile of data.</p>
<p>Second, data structures can make your apps faster. With the right data structure, you’ll be able to retrieve, modify, and sort data in the blink of an eye.</p>
<p>And finally, they help you solve problems like a boss**.** Whether you need to sort stuff, search through a lot of data, or handle some complex information, data structures are your go-to solution.</p>
<h3 id="heading-example-storing-and-finding-customer-names"><strong>Example: Storing and Finding Customer Names</strong></h3>
<p>Okay, let’s say your app needs to store and retrieve customer names. You could do this in two ways. Let’s compare how an <strong>array</strong> and a <strong>hash table</strong> would handle this task.</p>
<p><strong>1. Using an Array:</strong><br>Imagine you’ve got a list of customer names, and they’re stored in a nice, neat array:</p>
<pre><code class="lang-text">customers = ["John", "Jane", "Emily", "Michael"]
</code></pre>
<p>If you want to grab the name of the person in the third spot (Emily), you can just point to the third index like this:</p>
<pre><code class="lang-text">print(customers[2])  // Output: Emily
</code></pre>
<p>Arrays are perfect if you have a simple, ordered list and you need to grab items by their position.</p>
<p><strong>2. Using a Hash Table:</strong><br>Now, let’s say you want to store customer names but also have a unique ID for each one. This is where a hash table (or dictionary) comes in handy. You use <strong>keys</strong> (like customer IDs) to quickly find their names. It’s much faster than searching through an array.</p>
<p>Here’s what it might look like in action:</p>
<pre><code class="lang-text">customers = { 101: "John", 102: "Jane", 103: "Emily", 104: "Michael" }
</code></pre>
<p>Now, if you want to find the customer with ID <code>103</code> (Emily), you just look up the key:</p>
<pre><code class="lang-text">print(customers[103])  // Output: Emily
</code></pre>
<p>Hash tables are awesome when you need to look things up fast. No searching, just straight to the point!</p>
<h3 id="heading-ready-to-dive-deeper"><strong>Ready to Dive Deeper?</strong></h3>
<p>If you're pumped to learn more about data structures, here are some resources to help you level up:</p>
<ul>
<li><p><a target="_blank" href="https://developers.google.com/learn">Google’s Data Structures Learning Guide</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/learn">freeCodeCamp’s Data Structures and Algorithms Course</a></p>
</li>
</ul>
<h2 id="heading-algorithms-performing-computations"><strong>Algorithms: Performing Computations</strong></h2>
<p>Okay, so you've got your data. Now what? Well, you need to process it—and that’s where <strong>algorithms</strong> step in. Think of algorithms as a set of instructions, kind of like a recipe, that tells your computer how to solve a problem or complete a task, step-by-step.</p>
<h3 id="heading-why-learn-algorithms-before-you-learn-a-programming-language"><strong>Why Learn Algorithms Before You Learn a Programming Language?</strong></h3>
<p>Before you dive into learning a programming language, it helps to first learn <strong>algorithms</strong>. Here’s why: algorithms teach you how to think like a problem-solver. They help you break down challenges, think logically, and tackle them systematically. And when you know your algorithms, you’re not just memorizing syntax – you’re also learning <strong>how to solve problems efficiently</strong>. That makes programming a lot easier.</p>
<h3 id="heading-lets-dive-into-some-cool-algorithms"><strong>Let’s Dive Into Some Cool Algorithms</strong></h3>
<p>There are a ton of algorithms out there, but let’s keep it simple for now with a couple of the most popular ones. These will get you started and make your code run smoother than ever.</p>
<h4 id="heading-1-bubble-sort-the-basics-of-sorting"><strong>1. Bubble Sort: The Basics of Sorting</strong></h4>
<p>Bubble Sort is the beginner’s go-to algorithm for sorting. It’s simple—kinda like flipping pancakes. You start with the first two elements in the list, compare them, and if they’re in the wrong order, you swap them. Then you move to the next pair and keep doing that until everything is in order.</p>
<p>Here’s how it works:</p>
<p>Imagine you’ve got a list of names that need to be sorted alphabetically:</p>
<pre><code class="lang-plaintext">John, Sarah, Anna, Jake, Emily
</code></pre>
<p>Bubble Sort will go through the list, comparing two names at a time, swapping them if they’re out of order. It repeats this process until the list is sorted.</p>
<p>At the end, your list will look like this:</p>
<pre><code class="lang-plaintext">Anna, Emily, Jake, John, Sarah
</code></pre>
<p>It’s simple, but not the fastest for long lists.</p>
<h4 id="heading-2-quick-sort-speedy-and-smart"><strong>2. Quick Sort: Speedy and Smart</strong></h4>
<p>If Bubble Sort is like a slow and steady turtle, Quick Sort is the speedy rabbit. It’s much faster, especially for larger data sets. Quick Sort is a “divide and conquer” algorithm—it breaks the list into smaller chunks, sorts them, and then puts everything back together.</p>
<p>Here’s how it works:</p>
<p>Let’s take that same list of names and use Quick Sort:</p>
<pre><code class="lang-plaintext">John, Sarah, Anna, Jake, Emily
</code></pre>
<p>First, pick a <strong>pivot</strong>—let’s say <strong>Jake</strong>. Now, split the list into two parts:</p>
<ul>
<li><p>Names that come <strong>before Jake</strong> alphabetically:</p>
<pre><code class="lang-plaintext">  Anna, Emily
</code></pre>
</li>
<li><p>Names that come <strong>after Jake</strong> alphabetically:</p>
<pre><code class="lang-plaintext">  John, Sarah
</code></pre>
</li>
</ul>
<p>Now, you repeat the process for each group. Keep picking pivots, splitting, and sorting until each group is small enough to be sorted easily. Then you just put everything back together, and voilà! Sorted list:</p>
<pre><code class="lang-bash">Anna, Emily, Jake, John, Sarah
</code></pre>
<p>Quick Sort is much faster than Bubble Sort, especially when you've got a lot of names to sort.</p>
<p>Again, there are many more algorithms to learn, but this should give you the basic idea of how they work and why they’re useful.</p>
<h3 id="heading-why-you-should-care-about-algorithms"><strong>Why You Should Care About Algorithms</strong></h3>
<p>So why does any of this matter? Here’s the deal: first, algorithms help you solve problems more easily by breaking them down problems into manageable steps.</p>
<p>Second, they make your code faster. With the right algorithm, you can make your code run like a sports car—fast!</p>
<p>They also allow you to manage big datasets more easily. Some algorithms, like Quick Sort, can handle large sets of data in no time, which is crucial when performance matters.</p>
<h3 id="heading-want-to-get-better-at-algorithms"><strong>Want to Get Better at Algorithms?</strong></h3>
<p>If you’re hungry for more algorithmic goodness, here’s where to go:</p>
<ul>
<li><p><a target="_blank" href="https://leetcode.com/">LeetCode</a></p>
</li>
<li><p><a target="_blank" href="https://www.hackerrank.com/">HackerRank</a></p>
</li>
</ul>
<p>And if you want to dive deeper, <a target="_blank" href="https://www.freecodecamp.org/news/learn-data-structures-and-algorithms-2/">here’s a free 48-hour course on the freeCodeCamp YouTube channel</a> on Data Structures and Algorithms.</p>
<h2 id="heading-programming-languages-displaying-the-output"><strong>Programming Languages: Displaying the Output</strong></h2>
<p>Finally, we get to programming languages. This is where most beginners start and it’s often why they struggle. Without a solid grasp of data structures and algorithms, programming languages can feel like trying to run before you can walk. You can learn the syntax, but without understanding the fundamentals, you’ll find it harder to write effective code.</p>
<h3 id="heading-why-programming-languages-should-come-last"><strong>Why Programming Languages Should Come Last:</strong></h3>
<p>Once you understand how to manage input (data structures) and process it (algorithms), learning a programming language becomes much easier. You can go beyond worrying about memorizing syntax you may not understand, and start applying logic and solving problems. Programming languages are the tools you use to implement your algorithms and data structures.</p>
<h3 id="heading-which-programming-language-to-learn"><strong>Which Programming Language to Learn:</strong></h3>
<p>When it comes to picking a programming language, it’s important to align your choice with your goals. The language you choose should be based on what you want to build and your career path.</p>
<p>Here’s a breakdown of some common choices:</p>
<ul>
<li><p><strong>JavaScript</strong>: If your goal is to build websites or web applications, JavaScript is essential. It runs in the browser and allows you to create dynamic and interactive websites. JavaScript also has a wide range of libraries and frameworks (like React, Node.js, and Vue) that can speed up development.</p>
</li>
<li><p><strong>Python</strong>: Known for its simplicity and readability, Python is a great choice for beginners. It’s widely used in data science, web development (with frameworks like Django and Flask), and machine learning. Python's syntax is clean and easy to understand, which makes it perfect for beginners focusing on building strong foundational skills.</p>
</li>
<li><p><strong>Java</strong>: If you’re interested in building large-scale, enterprise-level applications, Java is a solid choice. It's a statically typed language, meaning you define variable types explicitly. Java is commonly used in Android development and large backend systems.</p>
</li>
<li><p><strong>Swift</strong>: Swift is a great language for iOS app development. If you want to build mobile apps for the Apple ecosystem (iPhone, iPad, etc.), Swift is the way to go. It's fast, modern, and integrates well with Apple’s software development tools.</p>
</li>
<li><p><strong>C#</strong>: If you’re planning to work with game development, especially with Unity, C# is your best bet. It’s also used for enterprise applications, web development (via ASP.NET), and desktop apps.</p>
</li>
</ul>
<h3 id="heading-how-to-choose-the-right-language-for-you"><strong>How to Choose the Right Language for You:</strong></h3>
<p>The best way to choose a language is to consider what excites you and where you want to focus your efforts. Don’t worry too much about finding the "easiest" language – just focus on one that aligns with your interests.</p>
<p>For example, if you're excited about building websites, JavaScript might be the best place to start. If you’re interested in mobile apps, Swift or Kotlin could be a better fit.</p>
<p>Once you've picked a language, don’t stress about mastering every feature. Start with the basics and build projects that interest you. As you practice, you’ll naturally pick up more advanced concepts and techniques. The goal isn’t to become a master of syntax but to learn how to think like a programmer and solve problems effectively.</p>
<p><strong>Here are some tips for getting started:</strong></p>
<ol>
<li><p><strong>Start with Basics</strong>: Get comfortable with basic syntax and constructs. Learn how to write loops, conditional statements, and functions in your chosen language.</p>
</li>
<li><p><strong>Build Simple Projects</strong>: Apply what you've learned by building small projects. If you're learning JavaScript or Python, for example, try building a simple to-do list app or a calculator. These types of projects help solidify your understanding.</p>
</li>
<li><p><strong>Understand Libraries and Frameworks</strong>: Once you have the basics down, dive into libraries and frameworks that can help speed up development. For JavaScript, this might mean learning React or Vue. For Python, it could mean exploring Django or Flask.</p>
</li>
</ol>
<p><strong>Helpful Resources for Learning Programming Languages</strong>:</p>
<ul>
<li><p><a target="_blank" href="http://JavaScript.info">JavaScript.info</a></p>
</li>
<li><p><a target="_blank" href="http://Python.org">Python.org</a> <a target="_blank" href="https://docs.python.org/3/tutorial/">Tutorials</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/learn/">freeCodeCamp JavaScript Curriculum</a></p>
</li>
<li><p><a target="_blank" href="https://www.codecademy.com/learn/learn-python-3">Codecademy Python</a></p>
</li>
</ul>
<h2 id="heading-additional-skills"><strong>Additional Skills</strong></h2>
<p>While mastering the fundamentals of programming is essential, there are other skills that can significantly boost your development journey. These include problem-solving techniques, debugging, and version control. These skills might not seem as glamorous as learning a programming language, but they are just as important.</p>
<h3 id="heading-why-these-skills-matter"><strong>Why These Skills Matter:</strong></h3>
<p>Even if you know the syntax of a language, you’ll still face challenges when writing real-world applications. Problems like bugs, performance issues, and collaboration with other developers are inevitable. That’s why these additional skills are so valuable as they help you tackle these challenges more effectively.</p>
<p><strong>1. Problem-Solving:</strong><br>Problem-solving is at the core of programming. It’s not enough to know how to write code – you also need to know how to break down a problem and figure out the best way to solve it. A good programmer typically spends just as much time thinking about the problem as they do writing the solution.</p>
<ul>
<li><p><strong>Breaking down the problem</strong>: Start by understanding the problem. Ask questions like: What am I trying to achieve? What do I already know? What inputs do I have, and what do I expect as the output?</p>
</li>
<li><p><strong>Dividing it into smaller parts</strong>: Once you have a clear understanding, divide the problem into smaller, manageable pieces. This helps you focus on solving one part at a time rather than feeling overwhelmed by the entire issue.</p>
</li>
<li><p><strong>Looking for patterns</strong>: Often, problems in programming can be solved by recognizing patterns or using similar approaches you’ve learned before. Don’t be afraid to reuse code you’ve written or adapt it for a new task.</p>
</li>
</ul>
<p><strong>2. Debugging:</strong> No code is perfect, and bugs are inevitable. Debugging is the process of finding and fixing these bugs (problems in your code that cause it to mess up or not run). It's a skill that every programmer needs to learn because it helps you maintain and improve the quality of your code.</p>
<ul>
<li><p><strong>Using print statements</strong>: A simple and effective debugging technique is inserting print statements (or logging) in your code. This allows you to inspect variables and understand what’s happening at different stages of your program.</p>
</li>
<li><p><strong>Using a debugger</strong>: A debugger is a tool that allows you to step through your code line by line. It’s especially helpful when dealing with more complex bugs. Many programming environments, like Visual Studio Code or PyCharm, have built-in debuggers.</p>
</li>
<li><p><strong>Checking for common issues</strong>: Bugs often come from simple issues like typos, off-by-one errors, or misunderstanding the behavior of a function. Before diving into complex debugging, double-check your assumptions.</p>
</li>
</ul>
<p><strong>3. Version Control:</strong> Version control is a tool that helps developers manage changes to their code over time. It allows you to keep track of edits, collaborate with others, and revert to previous versions if something goes wrong.</p>
<ul>
<li><p><strong>Git</strong>: Git is the most widely used version control system. It allows you to save snapshots of your code, known as commits, and track the history of your project. It also makes collaboration easier by allowing multiple developers to work on the same project without stepping on each other's toes.</p>
</li>
<li><p><strong>GitHub</strong>: GitHub is a platform that hosts Git repositories and offers additional tools like issue tracking, project management, and code reviews. As you start collaborating with other developers, GitHub will become an invaluable resource.</p>
</li>
<li><p><strong>Basic Git commands</strong>: Learn basic Git commands like <code>git init</code>, <code>git commit</code>, <code>git push</code>, and <code>git pull</code>. Understanding these commands will allow you to manage your code effectively, both when working solo and with a team.</p>
</li>
</ul>
<p><strong>Helpful Resources for Additional Skills:</strong></p>
<ul>
<li><p><a target="_blank" href="https://leetcode.com/">LeetCode</a> (for problem-solving practice)</p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/debugging-tips/">freeCodeCamp Debugging Guide</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/gitting-things-done-book/">Book on Learning Git and GitHub</a></p>
</li>
<li><p><a target="_blank" href="https://git-scm.com/doc">Git Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://guides.github.com/">GitHub Guides</a></p>
</li>
</ul>
<h2 id="heading-how-to-build-the-right-foundations-practice-practice-practice"><strong>How to Build the Right Foundations: Practice, Practice, Practice</strong></h2>
<p>Okay, so you've got the theory down, but the real magic happens when you put what you've learned into action. Mastering data structures and algorithms isn't just about understanding them it’s about <strong>practicing</strong> until they feel second nature. Here’s how you can do that:</p>
<h3 id="heading-start-small-learn-the-basics"><strong>Start Small: Learn the Basics</strong></h3>
<p>Before you dive into big, complex problems, start by getting comfortable with the basics. Things like arrays, stacks, and queues are your best friends.</p>
<p><strong>Example Practice</strong>:<br>Start with problems that help you understand how these data structures work. Try writing a function that <strong>reverses a string</strong> using a stack. Here's a quick idea of what that might look like in JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reverseString</span>(<span class="hljs-params">inputString</span>) </span>{
    <span class="hljs-keyword">let</span> stack = [];
    <span class="hljs-comment">// Push all characters onto the stack</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; inputString.length; i++) {
        stack.push(inputString[i]);
    }

    <span class="hljs-keyword">let</span> reversedString = <span class="hljs-string">''</span>;
    <span class="hljs-comment">// Pop characters off the stack and add them to reversedString</span>
    <span class="hljs-keyword">while</span> (stack.length &gt; <span class="hljs-number">0</span>) {
        reversedString += stack.pop();
    }

    <span class="hljs-keyword">return</span> reversedString;
}

<span class="hljs-built_in">console</span>.log(reverseString(<span class="hljs-string">"hello"</span>));  <span class="hljs-comment">// Output: "olleh"</span>
</code></pre>
<p><strong>Why this helps</strong>: By using a stack to reverse a string, you're getting a hands-on feel for how stacks work—storing items and then removing them in reverse order. Practice small problems like this daily.</p>
<h3 id="heading-solve-real-problems-bring-algorithms-to-life"><strong>Solve Real Problems: Bring Algorithms to Life</strong></h3>
<p>Once you’ve nailed the basics, it’s time to apply what you've learned in real-world scenarios. Try using algorithms to solve problems that feel useful in real life.</p>
<p><strong>Example Practice</strong>:<br>Create a simple <strong>sorting program</strong> to arrange names alphabetically using an algorithm like <strong>Bubble Sort</strong> or <strong>Quick Sort</strong>. Here’s a quick example using Bubble Sort:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bubbleSort</span>(<span class="hljs-params">names</span>) </span>{
    <span class="hljs-keyword">let</span> n = names.length;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; n; i++) {
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = <span class="hljs-number">0</span>; j &lt; n - i - <span class="hljs-number">1</span>; j++) {
            <span class="hljs-keyword">if</span> (names[j] &gt; names[j + <span class="hljs-number">1</span>]) {
                <span class="hljs-keyword">let</span> temp = names[j];
                names[j] = names[j + <span class="hljs-number">1</span>];
                names[j + <span class="hljs-number">1</span>] = temp;
            }
        }
    }
    <span class="hljs-keyword">return</span> names;
}

<span class="hljs-keyword">let</span> names = [<span class="hljs-string">"John"</span>, <span class="hljs-string">"Emily"</span>, <span class="hljs-string">"Sarah"</span>, <span class="hljs-string">"Jake"</span>];
<span class="hljs-built_in">console</span>.log(bubbleSort(names));  <span class="hljs-comment">// Output: ['Emily', 'Jake', 'John', 'Sarah']</span>
</code></pre>
<p><strong>Why this helps</strong>: Solving real problems with algorithms deepens your understanding and gives you a tangible result. Whether you’re sorting names or calculating averages, real problems make the learning experience stick.</p>
<h3 id="heading-write-code-daily-make-it-a-habit"><strong>Write Code Daily: Make It a Habit</strong></h3>
<p>The secret to becoming a great programmer is consistency. Choose a programming language (Python, JavaScript, Java, or whatever you like) and make it a habit to write code <strong>every day</strong>. Even if it's just for 30 minutes, those 30 minutes add up.</p>
<p><strong>Example Practice</strong>:<br>Pick a small problem every day to practice applying data structures and algorithms. Use platforms like <a target="_blank" href="https://leetcode.com/">LeetCode</a> or <a target="_blank" href="https://www.hackerrank.com/">HackerRank</a> for daily challenges that fit your skill level. Here’s an example of a coding challenge you might find on these platforms:</p>
<ul>
<li><p><strong>Problem</strong>: Find the maximum number in a list of integers.</p>
<pre><code class="lang-javascript">  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">findMax</span>(<span class="hljs-params">nums</span>) </span>{
      <span class="hljs-keyword">let</span> maxNum = nums[<span class="hljs-number">0</span>];
      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> num <span class="hljs-keyword">of</span> nums) {
          <span class="hljs-keyword">if</span> (num &gt; maxNum) {
              maxNum = num;
          }
      }
      <span class="hljs-keyword">return</span> maxNum;
  }

  <span class="hljs-built_in">console</span>.log(findMax([<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>, <span class="hljs-number">0</span>, <span class="hljs-number">-5</span>]));  <span class="hljs-comment">// Output: 7</span>
</code></pre>
</li>
</ul>
<p><strong>Why this helps</strong>: Daily practice is key to internalizing what you’ve learned. It helps you stay sharp and gradually move from simple problems to more complex ones.</p>
<h3 id="heading-challenge-yourself-go-beyond-your-comfort-zone"><strong>Challenge Yourself: Go Beyond Your Comfort Zone</strong></h3>
<p>When you feel like you’ve got the basics down, it’s time to <strong>level up</strong>. Get involved in coding challenges or take on personal projects that push you outside of your comfort zone.</p>
<p><strong>Example Practice</strong>:<br>Join a hackathon or participate in a competitive coding challenge like <a target="_blank" href="https://codingcompetitions.withgoogle.com/">Google Code Jam</a> or <a target="_blank" href="https://codeforces.com/">Codeforces</a>. These challenges will push your problem-solving skills to the limit and help you learn new algorithms and techniques.</p>
<p><strong>Why this helps</strong>: Challenges force you to think critically and solve problems under time constraints. They help you learn faster and build confidence in your abilities.</p>
<h3 id="heading-stay-consistent-build-a-routine"><strong>Stay Consistent: Build a Routine</strong></h3>
<p>Consistency is the key to success in programming (and in most things, really). Set aside time every day or week to practice. Even if you don’t feel like it, just getting in some short coding sessions will make a huge difference in the long run.</p>
<p><strong>Example Practice</strong>:<br>Create a study plan with weekly goals. For example:</p>
<ul>
<li><p><strong>Week 1</strong>: Focus on basic data structures (arrays, stacks, queues).</p>
</li>
<li><p><strong>Week 2</strong>: Move on to sorting algorithms (Bubble Sort, Merge Sort).</p>
</li>
<li><p><strong>Week 3</strong>: Dive into more complex algorithms like Binary Search or Dynamic Programming.</p>
</li>
</ul>
<p>A routine ensures that you’re making steady progress. Plus, it makes sure you don’t get stuck on one topic for too long.</p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>Programming doesn’t have to be so hard. It’s like building a house: without a strong foundation, everything else feels unstable. But with the right basics like data structures, algorithms, and logical thinking, you’ll be amazed at how quickly you can create great things.</p>
<p>If someone had told me in 2016 that I’d be writing this article today, I wouldn’t have believed them. But with the right preparation, I turned frustration into confidence, and so can you.</p>
<p>Don’t let frustration hold you back. Focus on the fundamentals, practice consistently, and explore the resources I’ve shared. Remember, programming isn’t about being a genius it’s about preparation and persistence. You’ve got this!</p>
<p>If you have any questions, feel free to find me on Twitter at <a target="_blank" href="https://x.com/sprucekhalifa">@sprucekhalifa</a>, and don’t forget to follow me for more tips and updates. Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Cleaner JavaScript Code with The Ternary Operator ]]>
                </title>
                <description>
                    <![CDATA[ When you're coding in JavaScript, handling decisions through conditional statements is one of the core tasks you'll frequently encounter. One of the most commonly used methods for this is the ternary operator. But what exactly is it, and when should ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/write-cleaner-javascript-code-with-the-ternary-operator/</link>
                <guid isPermaLink="false">671bc601bf239575d6efca0c</guid>
                
                    <category>
                        <![CDATA[ Programming Tips ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwadamisi Samuel ]]>
                </dc:creator>
                <pubDate>Fri, 25 Oct 2024 16:23:29 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729865186546/5c28c610-6540-4363-814d-c3c0c532be69.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you're coding in JavaScript, handling decisions through conditional statements is one of the core tasks you'll frequently encounter. One of the most commonly used methods for this is the ternary operator. But what exactly is it, and when should you use it over the traditional if-else statement?</p>
<p>In this article, we’ll dive into the ternary operator, how it works, and when it’s the right choice compared to other conditional structures.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-the-ternary-operator">What is the Ternary Operator?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-ternary-operator-vs-if-else">The Ternary Operator vs. if-else</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-nested-ternary-operators-and-why-to-avoid-them">Nested Ternary Operators (And Why to Avoid Them)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-ternary-operator-vs-switch">The Ternary Operator vs. switch</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-use-case-for-the-ternary-operator">Example Use Case for the Ternary Operator</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-the-ternary-operator">What is the Ternary Operator?</h2>
<p>The ternary operator is a shorthand way to write conditional statements in JavaScript. It allows you to execute one of two expressions based on a condition, all in a single line. While this might sound complicated, its syntax is simple and intuitive once you understand how it works.</p>
<p>Here’s the basic structure:</p>
<pre><code class="lang-javascript">condition ? expressionIfTrue : expressionIfFalse;
</code></pre>
<p>In plain terms, if the <code>condition</code> evaluates to true, <code>expressionIfTrue</code> will run. If it evaluates to false, <code>expressionIfFalse</code> will run. The ternary operator gets its name from the fact that it involves three parts: a condition, a true expression, and a false expression.</p>
<h2 id="heading-how-to-use-the-ternary-operator">How to Use the Ternary Operator</h2>
<p>Let’s start with a basic example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> age = <span class="hljs-number">18</span>;

<span class="hljs-keyword">let</span> canVote = age &gt;= <span class="hljs-number">18</span> ? <span class="hljs-string">'Yes'</span> : <span class="hljs-string">'No'</span>;

<span class="hljs-built_in">console</span>.log(canVote);  <span class="hljs-comment">// Output: "Yes"</span>
</code></pre>
<p>In this example, the ternary operator checks if the <code>age</code> is greater than or equal to 18. If it is, the <code>canVote</code> variable is set to <code>'Yes'</code> – otherwise, it’s set to <code>'No'</code>. This is a concise alternative to the more traditional if-else structure.</p>
<h2 id="heading-the-ternary-operator-vs-if-else">The Ternary Operator vs. <code>if-else</code></h2>
<p>The ternary operator is often used as a shorthand for <code>if-else</code> statements when the condition is simple and can be expressed clearly in one line. Let’s take a look at how an if-else statement would handle the same logic from the previous example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> age = <span class="hljs-number">18</span>;
<span class="hljs-keyword">let</span> canVote;

<span class="hljs-keyword">if</span> (age &gt;= <span class="hljs-number">18</span>) {
  canVote = <span class="hljs-string">'Yes'</span>;
} <span class="hljs-keyword">else</span> {
  canVote = <span class="hljs-string">'No'</span>;
}

<span class="hljs-built_in">console</span>.log(canVote);  <span class="hljs-comment">// Output: "Yes"</span>
</code></pre>
<h3 id="heading-whats-the-difference-between-the-ternary-operator-and-if-else">What’s the Difference between the Ternary Operator and if-else?</h3>
<ul>
<li><p><strong>Conciseness</strong>: The ternary operator is significantly shorter, as it allows you to write conditionals in a single line. This can make your code cleaner and easier to read in certain scenarios.</p>
</li>
<li><p><strong>Readability</strong>: just keep in mind that readability can suffer if the condition or expressions become too complex. If you're dealing with multiple conditions or long expressions, the ternary operator can make the code harder to understand. The traditional if-else statement is cleaner and a better choice in this case.</p>
</li>
</ul>
<h3 id="heading-ternary-vs-if-else-which-is-better">Ternary vs if-else: Which is Better?</h3>
<p>Use the ternary operator when you need to make a quick, straightforward decision in your code. Avoid using it if the condition or the expressions are complex. In those cases, if-else is usually a better choice for clarity.</p>
<h3 id="heading-nested-ternary-operators-and-why-to-avoid-them">Nested Ternary Operators (And Why to Avoid Them)</h3>
<p>One common pitfall when using the ternary operator is nesting them. Although it's possible to nest ternary operators, it can quickly lead to code that’s difficult to read and maintain.</p>
<p>Here’s an example of a nested ternary operator:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> score = <span class="hljs-number">85</span>;

<span class="hljs-keyword">let</span> grade = score &gt;= <span class="hljs-number">90</span> ? <span class="hljs-string">'A'</span> : score &gt;= <span class="hljs-number">80</span> ? <span class="hljs-string">'B'</span> : <span class="hljs-string">'C'</span>;

<span class="hljs-built_in">console</span>.log(grade);  <span class="hljs-comment">// Output: "B"</span>
</code></pre>
<p>While this code works, it's not as readable as it could be. Your code becomes messy very quickly, and while collaborating on a project with other team members, it can become an issue if your code is not readable.</p>
<h3 id="heading-how-to-refactor-nested-ternary-operators">How to Refactor Nested Ternary Operators</h3>
<p>Instead of nesting ternary operators, it's often better to use an if-else structure or employ another approach like a switch statement if there are multiple conditions.</p>
<p>Here’s how the above logic would look with <code>if-else</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> score = <span class="hljs-number">85</span>;
<span class="hljs-keyword">let</span> grade;

<span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">90</span>) {
  grade = <span class="hljs-string">'A'</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">80</span>) {
  grade = <span class="hljs-string">'B'</span>;
} <span class="hljs-keyword">else</span> {
  grade = <span class="hljs-string">'C'</span>;
}

<span class="hljs-built_in">console</span>.log(grade); 
<span class="hljs-comment">// Output: "B"</span>
</code></pre>
<p>This version is much easier to read and maintain, especially if you have additional conditions to check.</p>
<h2 id="heading-ternary-operator-vs-switch">Ternary Operator vs. <code>switch</code></h2>
<p>While the <code>ternary operator</code> and <code>if-else statements</code> handle conditional logic well, there are times when you’ll need to compare a single variable to many possible values or outcomes. In this case, the <code>switch</code> statement is your best bet.</p>
<h3 id="heading-how-to-use-the-switch-statement">How to Use the Switch Statement</h3>
<p>We use <code>switch</code> when there are several possible values for a variable. The <code>ternary</code> operator is great for simple true/false checks, but <code>switch</code> makes it easier to handle multiple options.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> day = <span class="hljs-number">3</span>;
<span class="hljs-keyword">let</span> dayName;

<span class="hljs-keyword">switch</span> (day) {
  <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
    dayName = <span class="hljs-string">'Monday'</span>;
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
    dayName = <span class="hljs-string">'Tuesday'</span>;
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:
    dayName = <span class="hljs-string">'Wednesday'</span>;
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">default</span>:
    dayName = <span class="hljs-string">'Unknown'</span>;
}

<span class="hljs-built_in">console</span>.log(dayName);
<span class="hljs-comment">// Output: "Wednesday"</span>
</code></pre>
<p>In this code:</p>
<ol>
<li><p>We set <code>day</code> to 3. The goal is to match this number to a day of the week.</p>
</li>
<li><p>We use a <code>switch</code> statement to check the value of <code>day</code>:</p>
<ul>
<li><p>If <code>day</code> is 1, it assigns <code>'Monday'</code> to <code>dayName</code> and <code>break</code> exits the <code>switch</code> block.</p>
</li>
<li><p>If <code>day</code> is 2, it assigns <code>'Tuesday'</code> to dayName and <code>break</code> exits the <code>switch</code> block..</p>
</li>
<li><p>If day is 3, it assigns 'Wednesday' to dayName and <code>break</code> exits the <code>switch</code> block</p>
</li>
</ul>
</li>
<li><p>If <code>day</code> isn’t 1, 2, or 3, the <code>default</code> case runs, setting <code>dayName</code> to <code>'Unknown'</code>. Since <code>day</code> is 3 in this example, <code>dayName</code> is set to <code>'Wednesday'</code>, and that’s what gets printed.</p>
</li>
</ol>
<h3 id="heading-when-to-use-switch-instead-of-ternary">When to Use switch Instead of Ternary</h3>
<ul>
<li><p><strong>Multiple Conditions:</strong> If you’re checking multiple possible values for a single variable, <code>switch</code> is more appropriate than a ternary operator or <code>if-else</code>.</p>
</li>
<li><p><strong>Readability:</strong> The <code>switch</code> statement organizes complex conditional logic in a readable way, whereas trying to achieve the same result with ternary operators would be cumbersome and difficult to maintain.</p>
</li>
</ul>
<h3 id="heading-performance-considerations">Performance Considerations</h3>
<p>From a performance standpoint, there’s little difference between using a ternary operator and an if-else statement. JavaScript engines are optimized to handle both efficiently.</p>
<p>The real concern is code clarity and maintainability. If your ternary operator is making the code harder to read, the slight performance gain (if any) won’t be worth it.</p>
<h2 id="heading-example-use-case-for-the-ternary-operator">Example Use Case for the Ternary Operator</h2>
<p>In modern JavaScript frameworks like React, the ternary operator is often used for conditional rendering. Here’s an example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> isLoggedIn = <span class="hljs-literal">true</span>;

<span class="hljs-keyword">return</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    {isLoggedIn ? <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Welcome back!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> : <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Please log in.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
</code></pre>
<p>This makes the code concise and readable, especially when dealing with UI rendering logic where a simple decision needs to be made based on a state or prop.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The <code>ternary</code> operator is a powerful tool in JavaScript, allowing you to write concise and clear conditionals. However, it’s not always the best option. If your conditions are complex or readability is at risk, it’s better to stick with <code>if-else</code> statements or even a <code>switch</code> statement.</p>
<p>Key takeaways:</p>
<ul>
<li><p>Use the <code>ternary</code> operator for simple, one-line conditionals.</p>
</li>
<li><p>Avoid nesting ternary operators to keep your code readable.</p>
</li>
<li><p>For complex conditions or multiple checks, <code>if-else</code> or <code>switch</code> are better choices.</p>
</li>
</ul>
<p>With practice, you’ll get a feel for when the <code>ternary</code> operator makes sense, helping you write cleaner, more efficient JavaScript code.</p>
<p>Connect with me on <a target="_blank" href="https://www.linkedin.com/in/samuel-oluwadamisi-01b3a4236/?lipi=urn%3Ali%3Apage%3Ad_flagship3_feed%3BxAUJMbSgQTeDtb7n2d0mQQ%3D%3D">LinkedIn</a> and <a target="_blank" href="https://twitter.com/Data_Steve_">Twitter</a> if you found this helpful.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ From Concept to Code: How to Use AI Tools to Design and Build UI Components ]]>
                </title>
                <description>
                    <![CDATA[ How should a website look? What size should the buttons be? What layout should you use? Do your users need an OTP to reset their passwords? These are all questions that proper user interface and user experience (UI/UX) design answer. Design prototypi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-design-and-build-ui-components-with-ai/</link>
                <guid isPermaLink="false">670d75f8ed568d2eaf032897</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ekemini Samuel ]]>
                </dc:creator>
                <pubDate>Mon, 14 Oct 2024 19:50:16 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727885187463/f41f59b0-1ec0-4dbf-9d2a-437738584310.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>How should a website look? What size should the buttons be? What layout should you use? Do your users need an OTP to reset their passwords? These are all questions that proper user interface and user experience (UI/UX) design answer.</p>
<p>Design prototyping and testing are critical steps in optimizing website UX functionality. One <a target="_blank" href="https://www.forrester.com/report/The-Six-Steps-For-Justifying-Better-UX/RES117708">study</a> reported that improving <a target="_blank" href="https://www.hotjar.com/ux-design">UX design</a> led to a 400% increase in website conversions.</p>
<p>For such an important task, we need the best possible tools and resources we can get. And lately I’ve been enjoying using <a target="_blank" href="https://sourcegraph.com/cody">Sourcegraph’s Cody</a>. Cody is an AI tool that speeds up coding by helping you understand, write, and fix code. It accesses information from your entire codebase, and also references documentation pages, to provide context about functions and variables, help create new code, and improve your design system.</p>
<p>When combined with Tailwind CSS, which is a utility-first CSS framework, you can rapidly build UI components that are both functional and visually appealing.</p>
<p>In this tutorial, I’ll teach you how to build UIs faster with Cody and Tailwind CSS so you can leverage AI to streamline your workflow.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li><p>Basic understanding of JavaScript and front-end development.</p>
</li>
<li><p>Familiarity with Tailwind CSS.</p>
</li>
<li><p><a target="_blank" href="https://nodejs.org/en">Node.js</a> installed on your system.</p>
</li>
<li><p>A code editor like Visual Studio Code (VS Code).</p>
</li>
<li><p>Cody. <a target="_blank" href="https://sourcegraph.com/cody">Sign up on Sourcegraph</a> to get access (it’s free).</p>
</li>
</ul>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-will-we-be-building">What Will We Be Building?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-your-environment">How to Set Up Your Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-ui-components-with-ai">How to Create UI Components with AI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-more-complicated-uis">More Complicated UIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-improve-and-manage-existing-codebases-with-cody">How to Improve and Manage Existing Codebases with Cody</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-next-steps">Next Steps</a></p>
</li>
</ul>
<h2 id="heading-what-will-we-be-building">What Will We Be Building?</h2>
<p>Let’s build yet another Todo App, but with a spin. Each to-do item will have a timer that can be started, paused, and reset. This might be useful to track how much time you spend working on specific tasks.</p>
<p>From the <a target="_blank" href="https://sourcegraph.com/docs/cody/capabilities/chat#selecting-context">Cody docs</a>, Cody's chat allows you to add files and symbols as context in your messages.</p>
<ul>
<li><p>Type <code>@</code> and then a filename to include a file as a context.</p>
</li>
<li><p>Type <code>@#</code> and then a symbol name to include the symbol's definition as context. Functions, methods, classes, types, and so on are all symbols.</p>
</li>
</ul>
<p>Even though Cody will be doing most of the heavy lifting, it’s great to have a plan of how we want the UI to look. Here are the wireframes I created with <a target="_blank" href="https://wireframe.cc/">wireframe.cc</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667247231/ada73031-20ac-4e07-8203-abe7d85a4d55.png" alt="Wireframe of the task component - overview state and detail state" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667377001/5ac6b7ce-e2a8-41d6-8378-e5ba36bb546d.png" alt="Wireframe of the header and footer" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Alright! Let’s get into it.</p>
<h2 id="heading-how-to-set-up-your-environment">How to Set Up Your Environment</h2>
<p>This tutorial uses Visual Studio Code, but the development process is similar across other code editors. If you haven’t set up an editor yet, choose one that suits your preference and <a target="_blank" href="https://nodejs.org/en/learn/getting-started/how-to-install-nodejs">install Node.js</a>.</p>
<p>As of this article, Sourcegraph Cody is available on <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=sourcegraph.cody-ai">Visual Studio Code</a>, <a target="_blank" href="https://github.com/sourcegraph/sg.nvim#setup">Neovim</a>, <a target="_blank" href="https://sourcegraph.com/github.com/sourcegraph/cody@main/-/blob/cli/README.md">Cody CLI</a>, <a target="_blank" href="https://github.com/sourcegraph/emacs-cody">Emacs</a>, and <a target="_blank" href="https://plugins.jetbrains.com/plugin/9682-cody-ai-coding-assistant-with-autocomplete--chat">all JetBrains IDEs</a></p>
<h3 id="heading-how-to-add-cody-to-your-code-editor">How to add Cody to your code editor</h3>
<p>First, head over to the <a target="_blank" href="https://sourcegraph.com/cody/">Cody landing page</a>, click <strong>Get Cody for Free</strong>, and follow the prompts to sign up for a <a target="_blank" href="https://sourcegraph.com/">Sourcegraph</a> account using your preferred authentication method—GitHub, GitLab, or Google.</p>
<p>Pick the right option for your code editor. If you’re using Visual Studio Code, that would be, <strong>Install Cody in VS Code</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667454887/bccde86e-ac68-4425-a5d8-ffbc7febfd83.png" alt="Cody dashboard" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Opening the extension in your code editor prompts a sign-in:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667554900/d956efbb-9712-4096-a968-69854d3b98c0.png" alt="Signing into Cody with your preferred method." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>After signing in, we’re ready to go.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667586141/428a2eac-f383-4d7f-a63e-5fdd5638f227.jpeg" alt="The Cody chat on VS Code" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-set-up-the-project"><strong>How to set up the project</strong></h3>
<p>We’ll be working with a Vite + React + TailwindCSS project, but these ideas can easily be applied to any other framework (think Vue, Astro, Svelte, or regular Vanilla JS) or styling library (like Bootstrap, Bulma, Foundation CSS, or anything you’d prefer).</p>
<p>Run the following command to create a new React project, <strong>abc-planning-todo-app</strong>:</p>
<pre><code class="lang-bash">npm create vite@latest abc-planning-todo-app -- --template react
</code></pre>
<p>Then install Tailwind CSS:</p>
<pre><code class="lang-bash">npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
</code></pre>
<p>Next, update <code>tailwind.config.js</code> with this code to configure Tailwind CSS for the project:</p>
<pre><code class="lang-javascript">
<span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">content</span>: [
    <span class="hljs-string">"./index.html"</span>,
    <span class="hljs-string">"./src/**/*.{js,ts,jsx,tsx}"</span>,
  ],
  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {},
  },
  <span class="hljs-attr">plugins</span>: [],
}
</code></pre>
<p>Delete everything in <code>./src/index.css</code> and add the following Tailwind CSS directives:</p>
<pre><code class="lang-javascript">
@tailwind base;
@tailwind components;
@tailwind utilities;
</code></pre>
<h2 id="heading-how-to-create-ui-components-with-ai">How to Create UI Components with AI</h2>
<p>For consistency, let’s pick a color palette we’ll use for our to-do app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667638883/06819a4e-d7fd-4a24-b9b6-6ef8cda38b08.png" alt="Color palettes for the TODO UI" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>To use these colors in our Tailwind theme, we first need to give them descriptive names. Let's ask Cody for help!</p>
<p>For the rest of this article, all quotes represent a single prompt message used when chatting with Cody.</p>
<blockquote>
<p><em>What would be good names for the following hex colors?</em></p>
<ul>
<li><p><em>2B2D42</em></p>
</li>
<li><p><em>8D99AE</em></p>
</li>
<li><p><em>EDF2F4</em></p>
</li>
<li><p><em>EF233C</em></p>
</li>
<li><p><em>D90429</em></p>
</li>
</ul>
</blockquote>
<p>And then,</p>
<blockquote>
<p><em>Update</em> <strong><em>@tailwind.config.js</em></strong> <em>to include these 5 hex colors above:</em></p>
</blockquote>
<pre><code class="lang-javascript">
<span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">content</span>: [
    <span class="hljs-string">"./index.html"</span>,
    <span class="hljs-string">"./src/**/*.{js,ts,jsx,tsx}"</span>,
  ],
  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {
      <span class="hljs-attr">colors</span>: {
        <span class="hljs-string">'midnight-navy'</span>: <span class="hljs-string">'#2B2D42'</span>,
        <span class="hljs-string">'cloudy-sky'</span>: <span class="hljs-string">'#8D99AE'</span>,
        <span class="hljs-string">'ice-white'</span>: <span class="hljs-string">'#EDF2F4'</span>,
        <span class="hljs-string">'vibrant-red'</span>: <span class="hljs-string">'#EF233C'</span>,
        <span class="hljs-string">'ruby-red'</span>: <span class="hljs-string">'#D90429'</span>,
      },
    },
  },
  <span class="hljs-attr">plugins</span>: [],
}
</code></pre>
<h3 id="heading-how-to-create-basic-ui-components"><strong>How to create basic UI components</strong></h3>
<p>First, we create the Header component. With templates for relatively uncomplicated components (for example text inputs, headers, buttons and dropdowns), it’s as simple as providing a name for the component, and the copy content it should contain.</p>
<blockquote>
<p><em>Create a simple React Header Component with only company name on the far left and company motto on the far right. Use the Tailwind theme</em> <strong><em>@tailwind.config.js</em></strong></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667685164/728a496e-c018-4f09-ac4a-1926f322b3f1.png" alt="Adding the prompt to Cody" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Cody will generate a Header component, which you can then copy and paste into <code>./src/components/Header.jsx</code>.</p>
<p>You can also save the code to a new file in your project directly from the Cody chat.</p>
<pre><code class="lang-javascript">
<span class="hljs-comment">// ./src/components/Header.jsx</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">const</span> Header = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-midnight-navy text-ice-white p-4 flex justify-between items-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl font-bold"</span>&gt;</span>
        Company
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-cloudy-sky italic"</span>&gt;</span>
        Innovate. Create. Inspire.
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span>
  );
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Header;
</code></pre>
<p>Next, create the Footer component with this prompt:</p>
<blockquote>
<p><em>Create a simple React Footer Component with content Copyright C ABC Planning. Use the Tailwind theme</em> <strong><em>@tailwind.config.js</em></strong>*. Ensure footer is always at the bottom of the viewport*</p>
</blockquote>
<pre><code class="lang-javascript">
<span class="hljs-comment">// ./src/components/Footer.jsx</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">const</span> Footer = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-midnight-navy text-ice-white p-4 text-center fixed bottom-0 w-full"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;copy;</span> {new Date().getFullYear()} ABC Planning<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span></span>
  );
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Footer;
</code></pre>
<p>Let’s take a look at what we have so far.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667795664/bb16ff44-1403-499f-9441-9dcc804ea06b.png" alt="The generated Header and Footer" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-more-complicated-uis"><strong>More Complicated UIs</strong></h2>
<p>Next, we’ll need a container that will hold all our to-dos. Let’s ask Cody to create a to-do container component.</p>
<blockquote>
<p><em>Create a React TodoContainer Component that will serve as a container for Todo items. Use the Tailwind theme</em> <strong><em>@tailwind.config.js</em></strong>*. It should be mobile-responsive*.</p>
</blockquote>
<p>We tell Cody:</p>
<ul>
<li><p>What we want (a React component)</p>
</li>
<li><p>A brief description of how that component behaves/what it does (container for to-dos)</p>
</li>
<li><p>Any additional context – stylesheets, preferences, conventions, or anything else.</p>
</li>
</ul>
<pre><code class="lang-javascript">
<span class="hljs-comment">// ./src/components/TodoContainer.jsx</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">const</span> TodoContainer = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-ice-white min-h-screen p-4 sm:p-6 md:p-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"max-w-4xl mx-auto"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-midnight-navy text-3xl font-bold mb-6"</span>&gt;</span>Todo List<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"</span>&gt;</span>
          {children}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoContainer;
</code></pre>
<p>A good <a target="_blank" href="https://sourcegraph.com/blog/chat-oriented-programming-in-action">Chat-oriented programming</a> (CHOP) strategy is to separate the creation of markup from the creation of content. This simplifies the prompting process.</p>
<p>Cody can <a target="_blank" href="https://sourcegraph.com/blog/chat-oriented-programming-in-action">g</a>enerate both very well, but trying to fine-tune a single prompt for both tasks might be challenging. Each prompt should have a clear, specific goal for best results.</p>
<p>Let's now focus on the <code>TodoItem</code> component and split it into sections:</p>
<ul>
<li><p>There's a <strong>to-do header</strong> which consists of a title with a border.</p>
</li>
<li><p>There's a <strong>View details</strong> button.</p>
</li>
<li><p>There's a timer showing how long ago the to-do was started.</p>
</li>
<li><p>There are control buttons (which reflect the state of the to-do)</p>
<blockquote>
<p><em>Create a React TodoItem Component.</em></p>
<p><em>It consists of:</em></p>
<p><em>1. Task title. A header text with a border around it.</em></p>
<p><em>2. A simplified link/button "View details" below the todo header box.</em></p>
<p><em>3. A digital timer that shows hours, minutes, and seconds in the format 00:00:00.</em></p>
<p><em>4. Todo actions - "Start", "Pause", "Reset". Use relevant colors for each. The timer should be able to be started, paused and reset when the respective button is pressed.</em></p>
<p><em>It should look like a card (tall not wide) on a desktop.</em></p>
<p><em>It will be used with</em> <strong><em>@TodoContainer.jsx</em></strong></p>
<p><em>Use</em> <strong><em>@tailwind.config.js</em></strong> <em>theme</em></p>
</blockquote>
<pre><code class="lang-javascript">  <span class="hljs-comment">// ./src/components/TodoItem.jsx</span>
  <span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
  <span class="hljs-keyword">const</span> TodoItem = <span class="hljs-function">(<span class="hljs-params">{ title }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> [time, setTime] = useState(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">const</span> [isRunning, setIsRunning] = useState(<span class="hljs-literal">false</span>);
    useEffect(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">let</span> interval;
      <span class="hljs-keyword">if</span> (isRunning) {
        interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
          setTime(<span class="hljs-function">(<span class="hljs-params">prevTime</span>) =&gt;</span> prevTime + <span class="hljs-number">1</span>);
        }, <span class="hljs-number">1000</span>);
      }
      <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">clearInterval</span>(interval);
    }, [isRunning]);
    <span class="hljs-keyword">const</span> formatTime = <span class="hljs-function">(<span class="hljs-params">seconds</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> hours = <span class="hljs-built_in">Math</span>.floor(seconds / <span class="hljs-number">3600</span>);
      <span class="hljs-keyword">const</span> minutes = <span class="hljs-built_in">Math</span>.floor((seconds % <span class="hljs-number">3600</span>) / <span class="hljs-number">60</span>);
      <span class="hljs-keyword">const</span> secs = seconds % <span class="hljs-number">60</span>;
      <span class="hljs-keyword">return</span> [hours, minutes, secs].map(<span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> v.toString().padStart(<span class="hljs-number">2</span>, <span class="hljs-string">'0'</span>)).join(<span class="hljs-string">':'</span>);
    };
    <span class="hljs-keyword">const</span> handleStart = <span class="hljs-function">() =&gt;</span> setIsRunning(<span class="hljs-literal">true</span>);
    <span class="hljs-keyword">const</span> handlePause = <span class="hljs-function">() =&gt;</span> setIsRunning(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> handleReset = <span class="hljs-function">() =&gt;</span> {
      setIsRunning(<span class="hljs-literal">false</span>);
      setTime(<span class="hljs-number">0</span>);
    };
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-ice-white rounded-lg shadow-md p-4 flex flex-col space-y-4 h-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl font-bold text-midnight-navy border-2 border-midnight-navy rounded p-2 text-center"</span>&gt;</span>
          {title}
        <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-cloudy-sky hover:text-midnight-navy transition-colors"</span>&gt;</span>
          View details
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl font-mono text-midnight-navy text-center"</span>&gt;</span>
          {formatTime(time)}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex justify-between mt-auto"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleStart}</span> 
            <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-vibrant-red text-ice-white px-4 py-2 rounded hover:bg-ruby-red transition-colors"</span>
          &gt;</span>
            Start
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handlePause}</span> 
            <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-cloudy-sky text-midnight-navy px-4 py-2 rounded hover:bg-ice-white transition-colors"</span>
          &gt;</span>
            Pause
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleReset}</span> 
            <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-midnight-navy text-ice-white px-4 py-2 rounded hover:bg-cloudy-sky transition-colors"</span>
          &gt;</span>
            Reset
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  };
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoItem;
</code></pre>
<p>  From our wireframes, each to-do will have a detail state when its description is visible and can be updated. We’ll tell Cody to update the existing <code>TodoItem.jsx</code> file:</p>
<blockquote>
<p><em>Update</em> <strong><em>@TodoItem.jsx</em></strong> <em>to have a second state, when the view detail button is pressed. In this state, the TodoItem is composed of the following elements only:</em></p>
<p><em>1. Task header with the task title, same as before</em></p>
<p><em>2. A textbox with a description of the task</em></p>
<p><em>3. A save button, that emits an updateTask event, and switches the component back to its default state.</em></p>
<p><em>Include animations between the transition to create a clean feel and experience</em></p>
</blockquote>
<pre><code class="lang-javascript">
  <span class="hljs-comment">// ./src/components/TodoItem.jsx</span>
  <span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
  <span class="hljs-keyword">const</span> TodoItem = <span class="hljs-function">(<span class="hljs-params">{ title, description = <span class="hljs-string">''</span>, onUpdateTask }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> [time, setTime] = useState(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">const</span> [isRunning, setIsRunning] = useState(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> [isDetailView, setIsDetailView] = useState(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> [taskDescription, setTaskDescription] = useState(description);
    useEffect(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">let</span> interval;
      <span class="hljs-keyword">if</span> (isRunning) {
        interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
          setTime(<span class="hljs-function">(<span class="hljs-params">prevTime</span>) =&gt;</span> prevTime + <span class="hljs-number">1</span>);
        }, <span class="hljs-number">1000</span>);
      }
      <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">clearInterval</span>(interval);
    }, [isRunning]);
    <span class="hljs-keyword">const</span> formatTime = <span class="hljs-function">(<span class="hljs-params">seconds</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> hours = <span class="hljs-built_in">Math</span>.floor(seconds / <span class="hljs-number">3600</span>);
      <span class="hljs-keyword">const</span> minutes = <span class="hljs-built_in">Math</span>.floor((seconds % <span class="hljs-number">3600</span>) / <span class="hljs-number">60</span>);
      <span class="hljs-keyword">const</span> secs = seconds % <span class="hljs-number">60</span>;
      <span class="hljs-keyword">return</span> [hours, minutes, secs].map(<span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> v.toString().padStart(<span class="hljs-number">2</span>, <span class="hljs-string">'0'</span>)).join(<span class="hljs-string">':'</span>);
    };
    <span class="hljs-keyword">const</span> handleStart = <span class="hljs-function">() =&gt;</span> setIsRunning(<span class="hljs-literal">true</span>);
    <span class="hljs-keyword">const</span> handlePause = <span class="hljs-function">() =&gt;</span> setIsRunning(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> handleReset = <span class="hljs-function">() =&gt;</span> {
      setIsRunning(<span class="hljs-literal">false</span>);
      setTime(<span class="hljs-number">0</span>);
    };
    <span class="hljs-keyword">const</span> handleViewDetails = <span class="hljs-function">() =&gt;</span> setIsDetailView(<span class="hljs-literal">true</span>);
    <span class="hljs-keyword">const</span> handleSave = <span class="hljs-function">() =&gt;</span> {
      onUpdateTask({ title, <span class="hljs-attr">description</span>: taskDescription });
      setIsDetailView(<span class="hljs-literal">false</span>);
    };
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-ice-white rounded-lg shadow-md p-4 flex flex-col space-y-4 h-full transition-all duration-300 ease-in-out"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl font-bold text-midnight-navy border-2 border-midnight-navy rounded p-2 text-center"</span>&gt;</span>
          {title}
        <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        {isDetailView ? (
          <span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"flex-grow p-2 border-2 border-cloudy-sky rounded resize-none transition-all duration-300 ease-in-out"</span>
              <span class="hljs-attr">value</span>=<span class="hljs-string">{taskDescription}</span>
              <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setTaskDescription(e.target.value)}
              placeholder="Enter task description..."
            /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
              <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleSave}</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-vibrant-red text-ice-white px-4 py-2 rounded hover:bg-ruby-red transition-colors"</span>
            &gt;</span>
              Save
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span></span>
        ) : (
          <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
              <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleViewDetails}</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"text-cloudy-sky hover:text-midnight-navy transition-colors"</span>
            &gt;</span>
              View details
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl font-mono text-midnight-navy text-center"</span>&gt;</span>
              {formatTime(time)}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex justify-between mt-auto"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleStart}</span> 
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-vibrant-red text-ice-white px-4 py-2 rounded hover:bg-ruby-red transition-colors"</span>
              &gt;</span>
                Start
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handlePause}</span> 
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-cloudy-sky text-midnight-navy px-4 py-2 rounded hover:bg-ice-white transition-colors"</span>
              &gt;</span>
                Pause
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleReset}</span> 
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-midnight-navy text-ice-white px-4 py-2 rounded hover:bg-cloudy-sky transition-colors"</span>
              &gt;</span>
                Reset
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span></span>
        )}
      &lt;/div&gt;
    );
  };
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoItem;
</code></pre>
<p>  Now let’s create a new root component that makes use of our components:</p>
<blockquote>
<p><em>Generate an App.jsx that makes use of</em> <strong><em>@Header.jsx</em></strong>*,* <strong><em>@TodoItem.jsx</em></strong>*,* <strong><em>@TodoContainer.jsx</em></strong>*, and* <strong><em>@Footer.jsx</em></strong> <em>appropriately. Use simple JavaScript variables as state data and implement whatever functions are relevant. Have a minimum of 5 to-do items.</em></p>
</blockquote>
<pre><code class="lang-javascript">
  <span class="hljs-comment">// ./src/App.jsx</span>
  <span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
  <span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Header'</span>;
  <span class="hljs-keyword">import</span> TodoContainer <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/TodoContainer'</span>;
  <span class="hljs-keyword">import</span> TodoItem <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/TodoItem'</span>;
  <span class="hljs-keyword">import</span> Footer <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Footer'</span>;
  <span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [todos, setTodos] = useState([
      { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Complete project proposal'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Draft and finalize the project proposal for the client meeting.'</span> },
      { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Review code changes'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Go through the pull requests and provide feedback on the code changes.'</span> },
      { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Prepare presentation'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Create slides for the upcoming team meeting presentation.'</span> },
      { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Update documentation'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Review and update the project documentation with recent changes.'</span> },
      { <span class="hljs-attr">id</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">'Team meeting'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Attend the weekly team sync-up and discuss project progress.'</span> },
    ]);
    <span class="hljs-keyword">const</span> handleUpdateTask = <span class="hljs-function">(<span class="hljs-params">updatedTask</span>) =&gt;</span> {
      setTodos(todos.map(<span class="hljs-function"><span class="hljs-params">todo</span> =&gt;</span> 
        todo.id === updatedTask.id ? { ...todo, ...updatedTask } : todo
      ));
    };
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col min-h-screen"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex-grow"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">TodoContainer</span>&gt;</span>
            {todos.map(todo =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">TodoItem</span> 
                <span class="hljs-attr">key</span>=<span class="hljs-string">{todo.id}</span>
                <span class="hljs-attr">title</span>=<span class="hljs-string">{todo.title}</span>
                <span class="hljs-attr">description</span>=<span class="hljs-string">{todo.description}</span>
                <span class="hljs-attr">onUpdateTask</span>=<span class="hljs-string">{(updatedTask)</span> =&gt;</span> handleUpdateTask({ id: todo.id, ...updatedTask })}
              /&gt;
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">TodoContainer</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  };
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>  Here’s what we now have:</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726667940335/69911f3c-063b-40cc-80d6-27fd7b5aaa76.png" alt="Screenshot of the web app with the TodoList and TodoItem components" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-improve-and-manage-existing-codebases-with-cody">How to Improve and Manage Existing Codebases with Cody</h2>
<p>To further boost your productivity, Cody offers <a target="_blank" href="https://sourcegraph.com/docs/cody/capabilities/commands#prompts">prompts</a> and <a target="_blank" href="https://sourcegraph.com/docs/cody/capabilities/commands#commands">commands</a>.</p>
<p>You can save frequently used prompts for future use and share them with other team members within your organization. Commands offer quick, ready-to-use shortcuts for common coding tasks like writing, describing, fixing, and identifying code issues.</p>
<h3 id="heading-lets-add-documentation-to-our-code"><strong>Let’s add documentation to our code!</strong></h3>
<p>Firstly, select the code you would like to generate documentation for, we’ll use <code>TodoItem.jsx</code> for this example. Run the <strong>Document Code</strong> command, and we get a JSDoc docstring for the Footer component class.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726668014952/8c65682a-d931-46df-bf49-df447df74443.png" alt="Adding documentation to the code" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-lets-make-our-components-more-accessible-and-inclusive"><strong>Let’s make our components more accessible and inclusive</strong></h3>
<p>We can save our favorite and frequently used chat prompts on the <a target="_blank" href="https://sourcegraph.com/prompts/new"><strong>Prompt Library</strong></a> via the Sourcegraph's Web UI.</p>
<p>Let’s create a new prompt to improve the accessibility of our web app and ensure it adheres to the <a target="_blank" href="https://www.w3.org/WAI/standards-guidelines/wcag/">WCAG standard</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726668303154/a83398cb-90b7-4d28-9c8b-a15b4751366c.png" alt="Creating a new prompt on the Prompt Library" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>We can now use this prompt back in VS Code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726668369322/5279315d-283f-4d24-9a8d-62316f7ec3b4.png" alt="Using our newly created prompt in VS Code" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Above you can see the results from our accessibility prompt.</p>
<h3 id="heading-how-to-use-ai-responsibly-for-code-generation">How to Use AI Responsibly for Code Generation</h3>
<p>AI tools can significantly speed up your workflow, but it's essential to remember that AI is still a work in progress. As powerful as these tools can be, they can also make mistakes or "hallucinate," producing code that seems correct but doesn't actually work in your specific context.</p>
<p>To use AI responsibly for coding, it’s crucial to approach it from a point of understanding what needs to be done. Before relying on AI, make sure you have a solid grasp of the task at hand. AI works best when used as a productivity booster rather than a replacement for your expertise.</p>
<p>Here are a few key things to keep in mind when working with AI-generated code:</p>
<ul>
<li><p><strong>Double-check the code:</strong> Always run and test the code generated by AI. Even if it looks correct at first glance, there could be subtle errors or inefficiencies. It's your responsibility to ensure the code is functional and meets your project’s requirements.</p>
</li>
<li><p><strong>Understand the output:</strong> Before using any AI-suggested code, take time to understand how it works. This will allow you to quickly identify any mistakes and integrate the code effectively with the rest of your project.</p>
</li>
</ul>
<p>When used thoughtfully and carefully, AI can make your development process more efficient and help you focus on higher-level tasks. However, it’s essential to balance its use with human oversight to ensure the quality and accuracy of the code you're building.</p>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Creating user-friendly UIs has traditionally been time-consuming and difficult to manage. But using Cody, we created an interactive and attractive user interface with minimal effort. Cody supported us throughout the entire development process.</p>
<p>Here are some potential enhancements you can make:</p>
<ul>
<li><p>We can’t create or delete tasks. Try to fix that.</p>
</li>
<li><p>Develop a component to display total tasks and accumulated hours.</p>
</li>
<li><p>Add test cases for each component. We can do this quickly using the <strong>Generate Unit Tests</strong> command.</p>
</li>
</ul>
<p>If you enjoyed learning about Cody, you can try more of its features and applications. <a target="_blank" href="https://sourcegraph.com/cody">Sign up for a free, forever account</a> and boost your productivity designing, creating, documenting, and managing applications.</p>
<h3 id="heading-further-reading">Further reading</h3>
<p>If you want to learn more, you can read this article about chat-oriented programming (CHOP) and how to use Cody for it: <a target="_blank" href="https://sourcegraph.com/blog/chat-oriented-programming-in-action">Chat-oriented programming (CHOP) in action</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use SSH to Safely Connect to GitHub: A Simple Guide for Windows OS ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will explore the Secure Shell (SSH) protocol, a vital tool for securing network communications. SSH is widely used for accessing remote servers and managing code repositories securely, particularly in environments like GitHub. You... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-ssh-to-connect-to-github-guide-for-windows/</link>
                <guid isPermaLink="false">66f6c252eda714770c805738</guid>
                
                    <category>
                        <![CDATA[ ssh ]]>
                    </category>
                
                    <category>
                        <![CDATA[ networking ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Blogs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oghenekparobo Stephen ]]>
                </dc:creator>
                <pubDate>Fri, 27 Sep 2024 14:33:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727226065318/c1522ad1-df49-4bc9-aa31-567d4012585a.avif" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will explore the Secure Shell (SSH) protocol, a vital tool for securing network communications.</p>
<p>SSH is widely used for accessing remote servers and managing code repositories securely, particularly in environments like GitHub. You’ll learn about the fundamental concepts of SSH, how it works, and practical steps to set it up on Windows. We will cover everything from generating SSH keys to testing your connection and cloning repositories.</p>
<p>By the end of this guide, you will have a solid understanding of SSH and be equipped to enhance your workflow with secure connections.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-ssh">What is SSH?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-does-the-secure-shell-protocol-work">How Does the Secure Shell Protocol Work?</a></p>
</li>
</ol>
<ul>
<li><p><a class="post-section-overview" href="#heading-tcpip">TCP/IP</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-ssh-connection-process">The SSH Connection Process</a></p>
</li>
</ul>
<ol start="3">
<li><a class="post-section-overview" href="#heading-how-to-use-ssh-in-windows">How to Use SSH in Windows</a></li>
</ol>
<ul>
<li><p><a class="post-section-overview" href="#heading-windows-powershell-or-command-prompt">Windows PowerShell or Command Prompt</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-windows-subsystem-for-linux-wsl">Windows Subsystem for Linux (WSL)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-third-party-ssh-clients-for-example-putty">Third-Party SSH Clients (for example, PuTTY)</a></p>
</li>
</ul>
<ol start="4">
<li><a class="post-section-overview" href="#heading-how-to-use-ssh-in-windows-to-connect-to-github">How to Use SSH In Windows To Connect To GitHub</a></li>
</ol>
<ul>
<li><p><a class="post-section-overview" href="#heading-install-through-windows-optional-features">Install Through Windows Optional Features</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-download-and-install-from-github">Download And Install From Github</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-generate-ssh-keys">How To Generate SSH Keys</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-the-public-key-to-github">How To Add The Public Key To GitHub</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-the-ssh-connection">Testing The SSH Connection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-cloning-a-repository-using-ssh">Cloning A Repository Using SSH</a></p>
</li>
</ul>
<ol start="5">
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before you begin this tutorial, ensure you have the following:</p>
<ul>
<li><p><strong>Basic Understanding of Command Line</strong>: You should be familiar with using the command line interface (CLI) on Windows, including how to open PowerShell or Command Prompt.</p>
</li>
<li><p><strong>Windows Operating System</strong>: This tutorial is specifically tailored for users running Windows 10 or later versions.</p>
</li>
<li><p><strong>OpenSSH Client Installed</strong>: Ensure that you have the OpenSSH client installed on your system. You can check this by typing <code>ssh</code> in your command line interface.</p>
</li>
<li><p><strong>GitHub Account</strong>: You’ll need a GitHub for testing SSH connections and managing repositories.</p>
</li>
<li><p><strong>Text Editor</strong>: You’ll also need a code editor (like Visual Studio Code, Notepad++, or similar) to edit configuration files if needed.</p>
</li>
</ul>
<h1 id="heading-what-is-ssh">What is SSH?</h1>
<p><strong>SSH</strong> stands for secure shell (protocol). The secure shell protocol is a cryptographic network protocol for operating network services securely over an unsecured network.</p>
<p>In simpler terms, <strong>SSH</strong> is a way to safely use services on a network, like accessing a remote computer, even when the network itself isn’t fully secure. It protects your data and communications by scrambling (encrypting) everything, so no one can eavesdrop or tamper with it, even if they intercept it.</p>
<p>This is especially useful when connecting to services like GitHub, where you want to securely manage code on a remote server.</p>
<h3 id="heading-how-does-the-secure-shell-protocol-work">How Does The Secure Shell Protocol Work?</h3>
<p>SSH runs on the <a target="_blank" href="https://www.freecodecamp.org/news/what-is-tcp-ip-layers-and-protocols-explained/">TCP/IP set of rules</a> that computers use to communicate over the internet.</p>
<h3 id="heading-tcpip">TCP/IP</h3>
<p><strong>TCP</strong> stands for <strong>Transmission Control Protocol</strong>. It’s one of the core protocols in the <strong>TCP/IP suite</strong>, which is used to send data over the internet. The <strong>IP</strong> stands for <strong>Internet Protocol</strong>. It's part of the TCP/IP set of rules also, and its job is to guide packets of data to the right destination on the internet.</p>
<p>You can read more about the TCP/IP protocol <a target="_blank" href="https://www.cloudflare.com/learning/ddos/glossary/tcp-ip/">here</a> if you’d like to go deeper.</p>
<h3 id="heading-the-ssh-connection-process">The SSH Connection Process</h3>
<p>The <strong>Secure Shell protocol</strong> operates by establishing a secure connection between a client (your local machine) and a remote server.</p>
<p>First, the client initiates the connection by specifying the server's address (IP or domain) and login credentials. During the authentication phase, the server verifies the identity of the client, typically using a password or, more securely, SSH keys. These are a pair consisting of a private key stored on the client and a public key on the server.</p>
<p>Once authenticated, SSH encrypts all data transferred between the client and the server, ensuring confidentiality and integrity. This secure channel allows the client to execute commands, transfer files, and manage the server remotely as if physically present while safeguarding the data from potential interception or tampering.</p>
<p><strong>IP</strong> is responsible for addressing and routing the initial connection request from the client to the server. It ensures that the request, which includes the server's address, is sent to the correct destination.</p>
<p>Once the SSH connection request reaches the server, <strong>TCP</strong> establishes a reliable communication channel. It manages data transmission between the client and the server, ensuring that all packets are delivered accurately and in the correct order.</p>
<p>During the SSH session, <strong>TCP</strong> ensures that data <a target="_blank" href="https://www.cloudflare.com/learning/network-layer/what-is-a-packet/">packets</a> are correctly transmitted and reassembled, while <strong>IP</strong> handles the addressing. SSH then uses this secure and reliable channel to authenticate the client, encrypt all transferred data, and maintain a secure connection. This allows remote management and file transfer with confidentiality and integrity.</p>
<h2 id="heading-how-to-use-ssh-in-windows">How to Use SSH in Windows</h2>
<p>Windows provides a few different ways to use SSH:</p>
<h3 id="heading-windows-powershell-or-command-prompt"><strong>Windows PowerShell or Command Prompt</strong></h3>
<p>Windows comes with a built-in OpenSSH client. You can access this by opening PowerShell or Command Prompt and typing <code>ssh</code> This method is simple and requires no additional software.</p>
<h3 id="heading-windows-subsystem-for-linux-wsl"><strong>Windows Subsystem for Linux (WSL)</strong></h3>
<p>You can enable Windows Subsystem for Linux to run a Linux distribution directly on your Windows PC. Many Linux distros come with OpenSSH pre-installed, allowing you to use <code>ssh</code> commands from the Linux terminal. This method is great if you prefer a Linux-like environment.</p>
<h3 id="heading-third-party-ssh-clients-for-example-putty"><strong>Third-Party SSH Clients (for example, PuTTY)</strong></h3>
<p>If you prefer a standalone application, tools like PuTTY offer a graphical interface to manage SSH connections. PuTTY is widely used for connecting to servers and supports advanced options like saving connection profiles.</p>
<p>Windows 10 and later versions come with a native OpenSSH client, which allows you to securely connect to remote systems over an SSH (Secure Shell) connection.</p>
<h2 id="heading-how-to-use-ssh-in-windows-to-connect-to-github">How to Use SSH in Windows to Connect to GitHub</h2>
<p>If you're using Windows 10 or a later version, you can take advantage of the built-in SSH capabilities.</p>
<p>To get started, open your Windows Terminal or PowerShell, preferably as an administrator. In the command line interface, you can check if SSH is installed by typing the command <code>ssh</code>. This will confirm if the SSH client is available on your system.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727215416889/9985624e-ffe6-4aff-9e58-2fe3e6b36f26.png" alt="ssh cli command result, in this case a positive one that ssh is installed on the system" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>If you got the above image, it means SSH is available on your local system.</p>
<p>The first thing you'll need to set up an SSH connection is a pair of SSH keys – a public key and a private key. These are typically located in the <code>.ssh</code> directory in your home directory if generated already.</p>
<p>On Windows, your home directory is usually <code>C:\Users\owner\.ssh</code>. This is where you will find your SSH key files if they've already been generated.</p>
<p>You can easily install OpenSSH on your Windows system. There are a couple of ways to do this:</p>
<h3 id="heading-install-through-windows-optional-features">Install Through Windows Optional Features</h3>
<ol>
<li><p>Open the Windows Start menu and type "optional features" in the search bar.</p>
</li>
<li><p>Click on "Add or remove Windows optional features" to open the Optional Features window.</p>
</li>
<li><p>In the Optional Features window, scroll down and find the "OpenSSH Client" option.</p>
</li>
<li><p>Check the box next to it and click the "Install" button at the bottom to install the OpenSSH client.</p>
</li>
</ol>
<h3 id="heading-download-and-install-from-github">Download and Install from GitHub</h3>
<ol>
<li><p>Visit the GitHub repository for the Win32-OpenSSH (32-bit) or Win64-OpenSSH (64-bit) release, depending on your Windows version:</p>
<ul>
<li><p>32-bit: <a target="_blank" href="https://github.com/PowerShell/Win32-OpenShell/releases">https://github.com/PowerShell/Win32-OpenShell/releases</a></p>
</li>
<li><p>64-bit: <a target="_blank" href="https://github.com/PowerShell/Win64-OpenShell/releases">https://github.com/PowerShell/Win64-OpenShell/releases</a></p>
</li>
</ul>
</li>
<li><p>Download the latest .msi installer file that matches your Windows architecture.</p>
</li>
<li><p>Run the .msi installer to install the OpenSSH client on your system.</p>
</li>
</ol>
<p>After installing OpenSSH, you can now generate SSH keys by opening the Windows Terminal or PowerShell and running the <code>ssh-keygen</code> command. This will walk you through the process of creating a new public-private key pair that you can use to authenticate your SSH connections, such as to your GitHub account.</p>
<p>The public key can then be added to your GitHub account settings, allowing you to connect to your repositories using the SSH protocol instead of HTTPS. Remember to keep your private key safe and secure, as it provides access to your GitHub account.</p>
<p>By installing OpenSSH, you've set up the necessary foundation to work with SSH keys and establish secure connections to remote systems and services like GitHub.</p>
<p>Now you can check if the OpenSSH server is running by accessing the Windows Services utility. To do this, press the Windows key + R to open the Run dialog, then input "services.msc" and press Enter. This will open the services manager.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727217366905/348ece20-432c-443e-951c-5c61ae4c7b94.png" alt="a windows prompt, generated by clicking &quot;windows + r&quot;" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The services manager:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727217489636/dffca024-3cb2-4b2b-8a03-fb4a2b5cc629.png" alt="The services manager generated after clicking &quot;windows + r&quot;" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Scroll and look for the openSSH SSH server:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727217823859/accbf838-e6cb-491a-ad1a-affa0dd59230.png" alt="this is image indicates that openSSH server is runing in the system, automatically as far as the system is powered on " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>If the OpenSSH Server service is running in the Services window, it means that the OpenSSH server component is properly set up on your Windows system. This is an important first step in enabling secure SSH connections.</p>
<p>To ensure the OpenSSH server starts automatically whenever your PC is turned on, you can further configure the service's startup type. In the Services window, right-click on the "OpenSSH Server" service and select "Properties."</p>
<p>In the service properties, look for the "Startup type" dropdown and select "Automatic." This will ensure the OpenSSH Server service starts up automatically whenever your computer is powered on, rather than requiring you to manually start it each time.</p>
<p>By setting the OpenSSH Server service to start automatically, you can be confident that the server will be ready to accept incoming SSH connections at all times, without needing to remember to start it manually. This streamlines the process of using SSH-based authentication and remote access on your Windows machine.</p>
<p>Remember, having the OpenSSH Server service running and set to start automatically is just the first step. You'll still need to generate SSH keys and configure your GitHub account (or other services) to use the public key for authentication. But this initial setup of the OpenSSH server lays the foundation for seamless SSH usage going forward.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727218121688/a902b304-8103-49a5-8852-7094b4f70d5a.png" alt="opened the openSSH on the services manager" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Now that you've confirmed the OpenSSH Server is running on your Windows system, the next step is to ensure it can communicate through the Windows Firewall. The easiest way to do this is by using a PowerShell command.</p>
<p>Open PowerShell as an administrator and run the following command:</p>
<pre><code class="lang-plaintext">New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH SSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 -Program "C:\Program Files\OpenSSH\sshd.exe"
</code></pre>
<p>This PowerShell command will create a new firewall rule that allows inbound TCP traffic on port 22 (the default SSH port) for the OpenSSH Server executable located at "C:\Program Files\OpenSSH\sshd.exe".</p>
<p>Here's a breakdown of the different parameters used in the command:</p>
<ul>
<li><p><code>-Name sshd</code>: Assigns the name "sshd" to the new firewall rule.</p>
</li>
<li><p><code>-DisplayName 'OpenSSH SSH Server'</code>: Provides a descriptive display name for the rule.</p>
</li>
<li><p><code>-Enabled True</code>: Ensures the rule is active and enabled.</p>
</li>
<li><p><code>-Direction Inbound</code>: Specifies that the rule applies to inbound network traffic.</p>
</li>
<li><p><code>-Protocol TCP</code>: Configures the rule to allow TCP protocol connections.</p>
</li>
<li><p><code>-Action Allow</code>: Instructs the firewall to allow the specified traffic.</p>
</li>
<li><p><code>-LocalPort 22</code>: Sets the local port to 22, which is the default SSH port.</p>
</li>
<li><p><code>-Program "C:\Program Files\OpenSSH\sshd.exe"</code>: Identifies the specific program (the OpenSSH Server executable) that the rule should apply to.</p>
</li>
</ul>
<p>By running this PowerShell command, you're creating a dedicated firewall rule that permits the OpenSSH Server to communicate through the Windows Firewall, enabling you to establish secure SSH connections to your system.</p>
<p>Remember, it's always a good practice to review your firewall settings periodically, especially if you make changes to your network configuration or want to refine access to the OpenSSH Server further.</p>
<p>If successful, you should get this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727219301264/fb58d5ce-f8cf-49d2-9b56-6f1571c08652.png" alt=" dedicated firewall rule that permits the OpenSSH Server to communicate through the Windows Firewall" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-summary-of-the-above-cli-response">Summary of the above CLI response:</h4>
<ul>
<li><p><strong>Rule Name</strong>: sshd</p>
</li>
<li><p><strong>Display Name</strong>: OpenSSH SSH Server</p>
</li>
<li><p><strong>Direction</strong>: Inbound</p>
</li>
<li><p><strong>Action</strong>: Allow</p>
</li>
<li><p><strong>Enabled</strong>: True</p>
</li>
<li><p><strong>Profile</strong>: Any</p>
</li>
</ul>
<p>The rule is designed to allow inbound traffic, enabling external clients to connect to the server. The "Enabled" status confirms that the rule is currently active, while the "Profile" set to "Any" indicates that it applies to all network types, including public, private, and domain.</p>
<h4 id="heading-security-policies">Security Policies:</h4>
<ul>
<li><p><strong>Edge Traversal Policy</strong>: Block</p>
</li>
<li><p><strong>Loose Source Mapping</strong>: False</p>
</li>
<li><p><strong>Local Only Mapping</strong>: False</p>
</li>
</ul>
<p>The "EdgeTraversalPolicy" is configured to "Block," preventing traffic from traversing the network boundary, specifically disallowing connections from public networks to private ones. This helps enhance security by mitigating potential vulnerabilities.</p>
<p>The settings for "LooseSourceMapping" and "LocalOnlyMapping" are both set to false, ensuring that only direct connections are allowed without additional mapping.</p>
<h4 id="heading-status-and-enforcement">Status and Enforcement:</h4>
<ul>
<li><p><strong>Primary Status</strong>: OK</p>
</li>
<li><p><strong>Status</strong>: The rule was parsed successfully from the store.</p>
</li>
<li><p><strong>Enforcement Status</strong>: NotApplicable</p>
</li>
<li><p><strong>Policy Store Source</strong>: PersistentStore</p>
</li>
<li><p><strong>Policy Store Source Type</strong>: Local</p>
</li>
</ul>
<p>The "Status" field confirms that the rule has been successfully parsed from the policy store, indicating no configuration issues. The "EnforcementStatus" marked as "NotApplicable" suggests there are no restrictions that would prevent the rule from being enforced.</p>
<p>Remember, to set up an SSH connection we need a pair of SSH keys – a public key and a private key. Let’s see how to do that now.</p>
<h3 id="heading-how-to-generate-ssh-keys">How to Generate SSH Keys</h3>
<ul>
<li><p>Open your Windows Terminal or PowerShell.</p>
</li>
<li><p>Run the command <code>ssh-keygen</code> to generate a new SSH key pair.</p>
</li>
<li><p>Follow the prompts to specify the save location and passphrase (optional) for your keys.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727220068539/7ee02096-da9e-4a26-8da8-106ec2dcefee.png" alt="cli command for generating ssh keys and its response" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You will get what you see in the above image if you’re successful.</p>
<p>The public key will be saved as <code>id_</code><a target="_blank" href="http://rsa.pub"><code>rsa.pub</code></a> in the <code>.ssh</code> directory of your user's home folder (for example, <code>C:\Users\you\.ssh\id_</code><a target="_blank" href="http://rsa.pub"><code>rsa.pub</code></a>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727220167279/b04fed4a-17d1-49e6-ad34-d5cb41692d13.png" alt="viewing the private and public ky oon our local system in our home-directory/.ssh" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-add-the-public-key-to-github">How to Add the Public Key to GitHub</h3>
<ul>
<li><p>Log in to your GitHub account and go to your account settings.</p>
</li>
<li><p>Navigate to the "SSH and GPG keys" section.</p>
</li>
<li><p>Click on the "New SSH key" button. Give your key a descriptive title, and then copy the contents of the <code>id_</code><a target="_blank" href="http://rsa.pub"><code>rsa.pub</code></a> file (your public key) into the "Key" field.</p>
</li>
<li><p>Click "Add SSH key" to save the new key.</p>
</li>
</ul>
<h3 id="heading-testing-the-ssh-connection">Testing the SSH Connection</h3>
<p>In your Windows Terminal or PowerShell, execute the following command to test your SSH connection to GitHub:</p>
<pre><code class="lang-plaintext">bashCopy codessh -T git@github.com
</code></pre>
<p>If prompted, enter your passphrase if you set one during the key generation process. If you did not set a passphrase, simply type "yes" when asked for a response to the handshake.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727220975104/6ed54e15-00a9-4cad-b95e-3424be855596.png" alt="6ed54e15-00a9-4cad-b95e-3424be855596" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>If the connection is successful, you should see a message like "Hi username! You've successfully authenticated, but GitHub does not provide shell access."</p>
<p>You can solve this by following the process <a target="_blank" href="https://gist.github.com/bsara/5c4d90db3016814a3d2fe38d314f9c23">here</a>.</p>
<h3 id="heading-cloning-a-repository-using-ssh">Cloning a Repository Using SSH</h3>
<p>Navigate to one of your GitHub repositories and copy the SSH clone URL, which typically starts with <a target="_blank" href="mailto:git@github.com"><code>git@github.com</code></a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727222441040/926444a1-bdf8-4f33-980c-0c2c87691a6b.png" alt="ssh link to clone a github repo" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In your local terminal, run the command <code>git clone</code> <a target="_blank" href="mailto:git@github.com"><code>git@github.com</code></a><code>:username/repository.git</code> to clone the repository using the SSH protocol.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You now have SSH working between your Windows computer and your GitHub account. This means you can work with your GitHub projects more easily and securely.</p>
<h3 id="heading-why-ssh-is-cool">Why SSH is Cool:</h3>
<ol>
<li><p>It's super secure. SSH scrambles your data so others can't snoop on it.</p>
</li>
<li><p>It's convenient. No more typing passwords all the time!</p>
</li>
<li><p>It's flexible. You can use it for more than just GitHub.</p>
</li>
<li><p>You can have different "keys" for different projects.</p>
</li>
<li><p>It works well with automatic coding tools.</p>
</li>
</ol>
<p>But it’s not perfect:</p>
<ol>
<li><p>Keeping track of many SSH keys can be a headache.</p>
</li>
<li><p>If someone gets your private key, they could access your stuff.</p>
</li>
<li><p>Setting it up the first time can be tricky.</p>
</li>
<li><p>You need to remember to change your keys yourself for extra safety.</p>
</li>
<li><p>Some networks might block SSH, which can be annoying.</p>
</li>
</ol>
<p>Remember to keep your private SSH key safe. It's like a special password for your GitHub account, so guard it well.</p>
<p>Even with these small downsides, SSH is still awesome for most coders. You are now all set to work on your GitHub projects more easily and safely. Have fun with your improved coding setup, and keep learning about ways to keep your work secure.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
