<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Patrick Mbithi</title>
    <description>The latest articles on DEV Community by Patrick Mbithi (@patrick_mbithi_).</description>
    <link>https://dev.to/patrick_mbithi_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3238685%2F1741e31c-b241-478a-aca3-943dd960e6a6.png</url>
      <title>DEV Community: Patrick Mbithi</title>
      <link>https://dev.to/patrick_mbithi_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/patrick_mbithi_"/>
    <language>en</language>
    <item>
      <title>What a Calorie Counter Taught Me About Inputs I Didn't Know I Needed to Learn</title>
      <dc:creator>Patrick Mbithi</dc:creator>
      <pubDate>Wed, 10 Jun 2026 19:44:00 +0000</pubDate>
      <link>https://dev.to/patrick_mbithi_/what-a-calorie-counter-taught-me-about-inputs-i-didnt-know-i-needed-to-learn-4j0j</link>
      <guid>https://dev.to/patrick_mbithi_/what-a-calorie-counter-taught-me-about-inputs-i-didnt-know-i-needed-to-learn-4j0j</guid>
      <description>&lt;p&gt;A calorie counter sounds like one of those beginner projects that teaches you basic math and maybe some DOM stuff. Set a budget, log meals, subtract, done. I figured I'd knock it out in an afternoon.&lt;/p&gt;

&lt;p&gt;The math part took twenty minutes. The rest of it was humbling.&lt;/p&gt;




&lt;h2&gt;
  
  
  Regex was the first wall
&lt;/h2&gt;

&lt;p&gt;I'd seen regex before and mostly avoided it. This project forced me to actually write some.&lt;/p&gt;

&lt;p&gt;The problem is user input. People type things like &lt;code&gt;+200&lt;/code&gt; or &lt;code&gt;- 150&lt;/code&gt; into calorie fields. Technically valid numbers. But if you pass those strings directly to &lt;code&gt;Number()&lt;/code&gt;, you get &lt;code&gt;NaN&lt;/code&gt;, which breaks everything quietly. The fix is a cleaning function that strips the noise before parsing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cleanInputString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;+-&lt;/span&gt;&lt;span class="se"&gt;\s]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple enough. But I had to actually understand why the &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;-&lt;/code&gt; need to be inside the character class &lt;code&gt;[]&lt;/code&gt; rather than sitting outside it, and what &lt;code&gt;\s&lt;/code&gt; is catching, and why the &lt;code&gt;g&lt;/code&gt; flag matters. None of that was hard once I looked it up. I just hadn't looked it up before.&lt;/p&gt;

&lt;p&gt;The second regex was stranger. Browsers will accept scientific notation in a &lt;code&gt;type="number"&lt;/code&gt; field. Type &lt;code&gt;1e10&lt;/code&gt; and the input won't complain. Your app will then cheerfully try to add ten billion calories to breakfast. So there's a second check that specifically catches that pattern and rejects it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isInvalidInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+e&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+/i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would not have thought to look for that on my own. Good thing the curriculum did.&lt;/p&gt;




&lt;h2&gt;
  
  
  How functions handle failure
&lt;/h2&gt;

&lt;p&gt;The project uses a global &lt;code&gt;isError&lt;/code&gt; flag a boolean that resets to &lt;code&gt;false&lt;/code&gt; at the start of every calculation, then flips to &lt;code&gt;true&lt;/code&gt; inside &lt;code&gt;getCaloriesFromInputs&lt;/code&gt; if bad input is found. The main calculation function checks it after gathering all the values and returns early if something went wrong.&lt;/p&gt;

&lt;p&gt;It works fine. But sitting with it made me think about the other ways you could handle this. Return &lt;code&gt;null&lt;/code&gt; and check for it upstream. Throw an error and catch it. Return an object with a status field. Each approach shifts where the responsibility sits.&lt;/p&gt;

&lt;p&gt;I hadn't thought about that before. This project was the first time I had to actually notice the choice being made, even if I didn't make it myself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building the DOM on the fly
&lt;/h2&gt;

&lt;p&gt;The "Add Entry" button injects new form fields into whatever meal category the user has selected. It does that with &lt;code&gt;insertAdjacentHTML&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;targetInputContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertAdjacentHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beforeend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HTMLString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The HTML is a template literal with the entry number and category name baked into the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;for&lt;/code&gt; attributes. That's what keeps labels connected to their inputs as you keep adding rows. If those attributes don't match, clicking a label does nothing.&lt;/p&gt;

&lt;p&gt;Before I saw this pattern I would have assumed you'd need a framework for dynamic forms. Turns out you don't. You just need to understand what &lt;code&gt;insertAdjacentHTML&lt;/code&gt; does and why the attributes matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  The clear function almost felt like a reward
&lt;/h2&gt;

&lt;p&gt;After all of that, the form reset was almost relaxing. Loop through the input containers, set &lt;code&gt;innerHTML&lt;/code&gt; to an empty string, clear the budget field, hide the output div. Four things. No edge cases. Done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;clearForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputContainers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.input-container&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;inputContainers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;budgetNumberInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I appreciated that.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I actually took away
&lt;/h2&gt;

&lt;p&gt;Going in, I thought this was a project about arithmetic and maybe some querySelector practice. What it actually drilled was input handling all the ways user input can be malformed, all the places where "valid" and "correct" are two different things, and how much of your validation logic exists specifically to close the gap between what the browser accepts and what your math can safely process.&lt;/p&gt;

&lt;p&gt;That's probably obvious to experienced devs. For me, it was the thing I didn't know I was going to learn.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>devjournal</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Learning JavaScript With freeCodeCamp: What the RPG Project Teaches You</title>
      <dc:creator>Patrick Mbithi</dc:creator>
      <pubDate>Thu, 04 Jun 2026 16:49:45 +0000</pubDate>
      <link>https://dev.to/patrick_mbithi_/learning-javascript-with-freecodecamp-what-the-rpg-project-teaches-you-2ecm</link>
      <guid>https://dev.to/patrick_mbithi_/learning-javascript-with-freecodecamp-what-the-rpg-project-teaches-you-2ecm</guid>
      <description>&lt;p&gt;&lt;strong&gt;tags:&lt;/strong&gt; javascript, beginners, webdev, freecodecamp&lt;/p&gt;




&lt;p&gt;I've tried to "learn JavaScript" more times than I want to admit. Courses, YouTube videos, the usual. I'd get through loops and think I understood them, then open a blank file and have nothing to show for it.&lt;/p&gt;

&lt;p&gt;freeCodeCamp's RPG project is different. Not because it's fun (it is), but because it forces you to actually &lt;em&gt;use&lt;/em&gt; the concepts instead of just nodding at them.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you're building
&lt;/h2&gt;

&lt;p&gt;It's a browser-based RPG. You fight monsters -- a slime, a fanged beast, a dragon -- collect gold, buy weapons, manage health. The whole thing lives in &lt;code&gt;index.html&lt;/code&gt; with a JavaScript file doing the heavy lifting. No frameworks. No libraries. Just you and the DOM.&lt;/p&gt;

&lt;p&gt;Here's what that looks like when it clicks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;town square&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Go to store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Go to cave&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fight dragon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Buy 10 health (10 gold)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Buy weapon (30 gold)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Go to town square&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That array of objects is the entire game state engine. When you first write it out, it looks like a lot of typing. Then you realize: every button, every screen transition, every monster is just pulling from this one structure. That's when data structures stop being an abstract concept.&lt;/p&gt;




&lt;h2&gt;
  
  
  The thing nobody tells you about arrays of objects
&lt;/h2&gt;

&lt;p&gt;I spent probably 45 minutes confused about why &lt;code&gt;locations[3].name&lt;/code&gt; worked but &lt;code&gt;location.name&lt;/code&gt; didn't. Obvious in hindsight. At the time it felt like the floor had dropped out.&lt;/p&gt;

&lt;p&gt;What actually made it click was the &lt;code&gt;update&lt;/code&gt; function -- one function that takes a location object and rewires the whole UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;monsterStats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;button1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;button2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;button3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;button1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;button2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;button3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time the player clicks something, you're not writing new HTML. You're just swapping the data the function reads. That pattern -- separate your data from your rendering -- is something I now see everywhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where it gets genuinely tricky
&lt;/h2&gt;

&lt;p&gt;The combat system. You need to track player health, monster health, the current weapon, and whether the monster is still alive. And you need to update the DOM after every single action without losing track of any of it.&lt;/p&gt;

&lt;p&gt;I got it wrong twice before I understood why global variables exist in small programs like this. Not because they're good practice forever -- they're not -- but because the alternative (passing state through every function) gets complicated fast. This project teaches you &lt;em&gt;why&lt;/em&gt; people care about state management. Not as a concept. As a problem you personally ran into.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Easter egg that teaches you something real
&lt;/h2&gt;

&lt;p&gt;There's a secret number guessing minigame hidden in the RPG. The randomness that powers it uses the same &lt;code&gt;Math.floor(Math.random() * X)&lt;/code&gt; pattern as the combat system. The first time I noticed I'd written the same two lines in three different places, I understood what "don't repeat yourself" actually means as a constraint, not just advice.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd tell someone starting this project
&lt;/h2&gt;

&lt;p&gt;Don't read ahead. Seriously. The temptation is to look at the full solution when you get stuck on the &lt;code&gt;buyWeapon&lt;/code&gt; function or the monster health math. That's the exact moment where fighting through it pays off. Google the specific thing you don't understand. That's different from looking at the answer.&lt;/p&gt;

&lt;p&gt;Also, the dragon fight is hard by design. You're probably not missing something. It's just hard.&lt;/p&gt;




&lt;p&gt;I'm still early in my JavaScript journey, but this project changed how I think about learning to code. Writing something that runs -- that has a win condition, a lose condition, and a secret cheat code -- is worth more than any number of practice exercises where you guess what the output will be.&lt;/p&gt;

&lt;p&gt;If you're somewhere in the middle of the freeCodeCamp JavaScript curriculum and this project is next: you're going to be fine. It's longer than it looks. It's also better than it looks.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with: vanilla JS, freeCodeCamp's JavaScript Algorithms and Data Structures curriculum&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>learning</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
