<?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: Luke Brannagan</title>
    <description>The latest articles on DEV Community by Luke Brannagan (@nevnet99).</description>
    <link>https://dev.to/nevnet99</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F304179%2Fd2eeb150-fd82-4fbb-8527-2472dad2d57c.jpg</url>
      <title>DEV Community: Luke Brannagan</title>
      <link>https://dev.to/nevnet99</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nevnet99"/>
    <language>en</language>
    <item>
      <title>Learning in 2025: How I Stopped Consuming and Started Understanding</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Sun, 26 Oct 2025 09:53:54 +0000</pubDate>
      <link>https://dev.to/nevnet99/learning-in-2025-how-i-stopped-consuming-and-started-understanding-2epd</link>
      <guid>https://dev.to/nevnet99/learning-in-2025-how-i-stopped-consuming-and-started-understanding-2epd</guid>
      <description>&lt;p&gt;In a world where you have access to all the content imaginable, I feel that some people have forgotten the appropriate way to learn. Content, be that a tutorial, a YouTube short, or a blog post like this, can promise you the world with an outcome, but conveniently leaves out the part about the hard work required to learn anything.&lt;/p&gt;

&lt;p&gt;Being stuck in tutorial hell can feel like pushing a rock up a hill. It’s ambiguous whether you’re actually learning anything. I remember spending weeks following a React tutorial only to realize I couldn’t build a single component without looking back at the video. That was the moment I realised I was consuming content, not learning.&lt;/p&gt;

&lt;p&gt;I’m going to share my approach to learning, specifically coding topics, but this could easily apply to other subjects too.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Risk of Modern Learning
&lt;/h2&gt;

&lt;p&gt;It’s worth mentioning that learning, in my opinion, is the most dangerous it has ever been. With the introduction of AI, it now takes mere seconds to create a LinkedIn post and shovel out whatever comes from your prompt into the post box and press publish.&lt;/p&gt;

&lt;p&gt;There is no watchman for the AI. Sometimes it gets things right, but it can also easily get things wrong, and you, the student on said topic, are none the wiser. I’m not saying avoid AI at all costs; it’s a useful tool, but that’s all it is—a tool. You should be validating its output by reading relevant documentation to ensure it’s correct.&lt;/p&gt;

&lt;p&gt;The allure of speed is intoxicating, but that speed comes at a cost, and that cost is understanding. When used wisely, AI can actually help you learn faster, but only if you stay in control of the process.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Dislike “Build X From Scratch” Videos
&lt;/h2&gt;

&lt;p&gt;It’s an abstraction. Someone has done all the hard work, read the docs, built prototypes, and created a project. Now it’s time to monetise and cash in on the thousands of people who think that loosely watching a video at 1.5x speed teaches them anything more than a surface-level understanding.&lt;/p&gt;

&lt;p&gt;These videos are purely monkey see, monkey do, and reward you with a nice GitHub repo without the real reward: understanding the rendering techniques of Next.js, for example.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Process for Learning Anything
&lt;/h2&gt;

&lt;p&gt;To start, I’d like to foreword that this is nothing new. It should be used less as a guide and more as a reminder of how to actually learn, rather than watching fruit dance on a YouTube short and expecting to know how to grow fruit.&lt;/p&gt;

&lt;p&gt;Remember that your time is money. Quite literally in today’s world, I could make a short that gives you 30 percent of a concept, so you watch it 15 times to fully understand it, only to forget it a week later and watch again another 15 times.&lt;/p&gt;

&lt;p&gt;Learning something is hard. Expect to put in the hours to fully understand a concept. Prepare yourself and accept that you might not learn it, if it’s a large one, in a day, a week, or even a month.&lt;/p&gt;

&lt;p&gt;First, I start with my note-taking tool. Personally, I use Obsidian because I like to own my data. However, any note-taking app or combination of writing tools, like a pen or pencil and some thin horizontal tree skin, will work.&lt;/p&gt;

&lt;p&gt;I start by writing a summary of what I’m going to learn and the questions I should be able to answer by the end of my learning session. If you want to get fancy, you can also add any linked topics that might branch off from this one.&lt;/p&gt;

&lt;p&gt;Next, I find resources that I trust: official documentation, MDN, or Wikipedia. We’re not in school—it’s normally accurate enough. I read, take notes, and if I get stuck, I’ll post that section into my LLM of choice, giving it the context of my notes rather than letting it just guess.&lt;/p&gt;

&lt;p&gt;From here, I have an understanding, not a complete or deep one yet, but a loose, untested understanding of the concept I’m learning. Now it’s time to put it into practice. Prototype on Stackblitz, build a portfolio piece, apply your theory, and try explaining the concept to someone. Keep it short—it also looks good on a CV.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Know You’re Actually Learning
&lt;/h2&gt;

&lt;p&gt;There are a few simple signs that tell me when something has clicked.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can explain the concept to someone else without looking at your notes.
&lt;/li&gt;
&lt;li&gt;You can build a smaller version of what you learned without copying code.
&lt;/li&gt;
&lt;li&gt;You can connect what you just learned to something you already know.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When those things start to happen, that’s when you know you’re truly learning.&lt;/p&gt;




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

&lt;p&gt;I’ve applied this pattern to almost all my learning over the past seven years and have been able to stay consistent with tech. I like to think I’m quite knowledgeable in the specialism I’ve chosen. It’s freeing to know that you can learn literally anything with enough hard work.&lt;/p&gt;

&lt;p&gt;True learning isn’t about speed. It’s about depth, patience, and curiosity.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🫖 Thinking in patterns not features</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Sat, 25 Oct 2025 14:23:44 +0000</pubDate>
      <link>https://dev.to/nevnet99/thinking-in-patterns-not-features-2fo0</link>
      <guid>https://dev.to/nevnet99/thinking-in-patterns-not-features-2fo0</guid>
      <description>&lt;p&gt;Patterns stand the test of time because they describe how something should work, not exactly how it’s built. The challenge comes when we design at too granular of a level.&lt;/p&gt;

&lt;p&gt;Building something that’s overly specific to a single feature quickly becomes hard to maintain, and documenting it, well is even harder.&lt;/p&gt;

&lt;p&gt;Think about the simple act of boiling water.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The pattern looks like this:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heat up the water
&lt;/li&gt;
&lt;li&gt;Wait until it boils
&lt;/li&gt;
&lt;li&gt;Congratulations, you’ve boiled water&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The implementation might look like this:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pour water into a kettle
&lt;/li&gt;
&lt;li&gt;Plug the kettle in
&lt;/li&gt;
&lt;li&gt;Press the switch
&lt;/li&gt;
&lt;li&gt;Wait for it to boil
&lt;/li&gt;
&lt;li&gt;Congratulations, you’ve boiled water&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern doesn’t change, only the method does. You could use a kettle, a campfire, or any other heat source however, the underlying logic stays the same.&lt;/p&gt;

&lt;p&gt;We can apply this same thinking to frontend development. Instead of building a hook that only handles one very specific use case, we can build a more general hook that defines the pattern, then inject the details as dependencies. It’s like choosing whether you use the kettle or the campfire. The steps stay consistent; only the context changes.&lt;/p&gt;

&lt;p&gt;This approach helps keep code consistent, easier to maintain, and simpler to explain. By focusing on patterns that represent the essence of what we’re trying to do, we can swap out the details without rewriting the logic every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  An Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌Imperative solution
&lt;/h3&gt;

&lt;p&gt;The imperative solution handles each step manually, tightly coupled to the feature, hard to reuse, document and test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useSignupSteps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStep&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setStep&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setStep&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&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;s&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// Steps are hard-coded here&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Create Account&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;profile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Set Up Profile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Confirm Details&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSignupSteps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧩 Pattern Version
&lt;/h3&gt;

&lt;p&gt;This version defines a general &lt;strong&gt;“steps pattern”&lt;/strong&gt; and lets you inject the specifics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useCallback&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;label&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UseStepsOptions&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;onStepChange&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Step&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useSteps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onStepChange&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;UseStepsOptions&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;onStepChange&lt;/span&gt;&lt;span class="p"&gt;?.(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;nextIndex&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;nextIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onStepChange&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;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;onStepChange&lt;/span&gt;&lt;span class="p"&gt;?.(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prevIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;prevIndex&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;prevIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onStepChange&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;goTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;onStepChange&lt;/span&gt;&lt;span class="p"&gt;?.(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onStepChange&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;current&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;goTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isFirst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isLast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="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;the key take aways from this document should be to design software more with patterns in mind than the imperative solution.&lt;/p&gt;

&lt;p&gt;For example, If you need to use &lt;code&gt;localStorage&lt;/code&gt; write a hook that handles all implementations of it rather than just thinking about your specific Kettle use case.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>react</category>
      <category>typescript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Mastering Project Governance: Achieving Codebase Excellence and Consistency (Frontend)</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Mon, 26 Jun 2023 17:37:49 +0000</pubDate>
      <link>https://dev.to/nevnet99/mastering-project-governance-achieving-codebase-excellence-and-consistency-frontend-2h65</link>
      <guid>https://dev.to/nevnet99/mastering-project-governance-achieving-codebase-excellence-and-consistency-frontend-2h65</guid>
      <description>&lt;p&gt;As a frontend developer, I have accumulated several tools over my 4 years of experience that have significantly simplified my projects and improved code quality. In this blog post, I will share these tools with you, emphasising the importance of enforcing code quality standards and consistency across a codebase. Please note that these tools are primarily focused on frontend development using React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why should you care about Project Governance?&lt;/li&gt;
&lt;li&gt;A Linter&lt;/li&gt;
&lt;li&gt;RFC (Request for Comments)&lt;/li&gt;
&lt;li&gt;Husky&lt;/li&gt;
&lt;li&gt;Plop&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why should you care about Project Governance?
&lt;/h2&gt;

&lt;p&gt;Imagine a scenario where we neglect project governance. In such a situation, several issues start to arise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spaghetti code:

&lt;ul&gt;
&lt;li&gt;Mixture of single and double quotes for strings.&lt;/li&gt;
&lt;li&gt;Multiple approaches to fetch and handle data.&lt;/li&gt;
&lt;li&gt;Different styling methods: some developers use styled-components, while others prefer Tailwind CSS.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Dependency hell:

&lt;ul&gt;
&lt;li&gt;Multiple libraries for fetching data.&lt;/li&gt;
&lt;li&gt;Various date libraries like date-fns and Moment.js.&lt;/li&gt;
&lt;li&gt;Numerous form handlers.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Onboarding difficulties: It becomes challenging to introduce new developers to a repository with 1000 packages serving different purposes and spaghetti code scattered throughout.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These examples only scratch the surface of the potential problems. Now, let's explore some solutions!&lt;/p&gt;

&lt;h2&gt;
  
  
  A Linter
&lt;/h2&gt;

&lt;p&gt;It goes without saying that using a linter is essential. If you don't have a linter locally installed in your project, your code will lack consistency and become a nightmare to manage. The industry standard combination is ESLint paired with Prettier.&lt;/p&gt;

&lt;p&gt;To set up ESLint and Prettier to automatically format your code according to strict yet clean rules upon saving, you can follow this guide for configuring it with most major IDEs: &lt;a href="https://github.com/wesbos/eslint-config-wesbos#with-vs-code" rel="noopener noreferrer"&gt;ESLint Configuration Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some recommended rulesets. I personally have been using Wes Bos's config for years and highly recommend it, but I will also list some common alternatives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/wesbos/eslint-config-wesbos" rel="noopener noreferrer"&gt;Wesbos / Wesbos Typescript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb" rel="noopener noreferrer"&gt;Airbnb / Airbnb Typescript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/eslint-config-fbjs" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a more comprehensive list of rulesets, you can refer to this &lt;a href="https://github.com/dustinspecker/awesome-eslint#configs-by-well-known-companiesorganizations" rel="noopener noreferrer"&gt;awesome-eslint repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  RFC
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Request_for_Comments" rel="noopener noreferrer"&gt;RFCs&lt;/a&gt; are a fantastic way to gather input from multiple developers before adding something to your repository. This could be a new dependency, a set of hooks to be built and used throughout the app, or even a restructuring of the project's folder structure.&lt;/p&gt;

&lt;p&gt;By introducing a small barrier, similar to a pull request, where you need to receive feedback from several individuals before adding a fifth date library to your repository, you can keep the number of dependencies low and encourage thoughtful consideration of each addition.&lt;/p&gt;

&lt;p&gt;RFCs can be implemented in various ways. Github supports them, but you can also set up a Slack channel dedicated to pending RFCs or incorporate them as subtasks in your Kanban board to track their status.&lt;/p&gt;

&lt;h2&gt;
  
  
  Husky
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/typicode/husky" rel="noopener noreferrer"&gt;Husky&lt;/a&gt; provides pre-commit powers! With Husky, you can run commands like &lt;code&gt;npm run lint --fixAll&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;just before creating a commit. You can also leverage Husky with TypeScript or testing frameworks to disallow commits with failing tests, adding an extra layer of security and consistency to your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plop
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://plopjs.com/" rel="noopener noreferrer"&gt;Plop&lt;/a&gt; is a tool for creating file templates using handlebars templates. One common problem is the inconsistency with code snippets, as each developer has their own way of quickly creating code from scratch using custom shortcuts. For example, I often use &lt;code&gt;rfac&lt;/code&gt; to generate a React component as an arrow function.&lt;/p&gt;

&lt;p&gt;Plop allows you to maintain consistent folder structures within your application and enables new developers to quickly onboard by creating components with a single command. You can even alias the command to something like &lt;code&gt;generate&lt;/code&gt;. For instance, typing &lt;code&gt;generate test&lt;/code&gt; would generate a test file with the necessary imports and snapshot tests already set up, if required. Plop simplifies the process of keeping your application's folder structure clean and consistent.&lt;/p&gt;




&lt;p&gt;By incorporating these tools into your frontend development workflow, you can significantly enhance code quality, maintain consistency, and make your life as a developer much easier.&lt;/p&gt;

&lt;p&gt;🚀 Feel free to reach out if you have any questions or thoughts. Happy coding!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>architecture</category>
      <category>learning</category>
    </item>
    <item>
      <title>Getting started with Pact and Consumer Driven Contract Testing</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Mon, 26 Jun 2023 10:27:09 +0000</pubDate>
      <link>https://dev.to/nevnet99/getting-started-with-pact-and-consumer-driven-contract-testing-with-react-1adl</link>
      <guid>https://dev.to/nevnet99/getting-started-with-pact-and-consumer-driven-contract-testing-with-react-1adl</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is Pact?&lt;/li&gt;
&lt;li&gt;What are Consumer Driven Contracts?&lt;/li&gt;
&lt;li&gt;Setting Up&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Pact?
&lt;/h2&gt;

&lt;p&gt;Pact is a family of frameworks that support various languages and offer an easy way to set up Consumer Driven Contract Testing (more on this later). Their website can be found &lt;a href="https://docs.pact.io/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, which provides comprehensive documentation if you prefer a different writing style.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Consumer Driven Contracts?
&lt;/h2&gt;

&lt;p&gt;Let's break it down:&lt;/p&gt;

&lt;h3&gt;
  
  
  What's a consumer?
&lt;/h3&gt;

&lt;p&gt;A consumer is typically a web app or anything that consumes the provider, which can also be another API.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's a provider?
&lt;/h3&gt;

&lt;p&gt;Usually, a provider refers to an API.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's a contract (or pact)?
&lt;/h3&gt;

&lt;p&gt;A contract is a file created by a test to expect a specific content type and body that should be sent to the consumer. For example, if you have a button on a form, clicking it may require passing a body and receiving a "complete" message in response.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does the testing theory work?
&lt;/h3&gt;

&lt;p&gt;First, we create a test on the consumer side, which generates our contract file. This contract should then be passed to the team handling the provider.&lt;/p&gt;

&lt;p&gt;Manually sending contracts to the provider team would be a pain, but that's where a Pact Broker like &lt;a href="https://pactflow.io/?utm_source=ossdocs&amp;amp;utm_campaign=pact_broker" rel="noopener noreferrer"&gt;PactFlow&lt;/a&gt; comes in. A Pact Broker easily integrates with your CI/CD system, and other teams can access contracts published on successful builds if desired.&lt;/p&gt;

&lt;p&gt;With some CI/CD setup, you can ensure that providers must satisfy the contracts to deploy, eliminating the chance of broken builds for all consumers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up
&lt;/h2&gt;

&lt;p&gt;For setting up Pact, I recommend the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/pact-foundation/pact-js" rel="noopener noreferrer"&gt;Pact Repo&lt;/a&gt;: This repo provides several helpful examples of writing Consumer Driven Contract testing.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/paucls/pact-consumer-contract-react-example" rel="noopener noreferrer"&gt;React Pact Consumer Contract Example&lt;/a&gt;: React developers can check out this repository to learn how to get up and running.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In summary, Pact is a family of frameworks that enable Consumer Driven Contract Testing. The process involves creating contracts on the consumer side and somehow passing them to the provider for validation. By using Pact, you can ensure reliable and smooth interactions between consumers and providers.&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions or thoughts. Happy coding!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>architecture</category>
      <category>react</category>
      <category>learning</category>
    </item>
    <item>
      <title>🔥 Hot Take: If you're not using Storybook you're doing FE Development wrong.</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Sun, 25 Jun 2023 20:43:57 +0000</pubDate>
      <link>https://dev.to/nevnet99/hot-take-if-youre-not-using-storybook-youre-doing-fe-development-wrong-2bk1</link>
      <guid>https://dev.to/nevnet99/hot-take-if-youre-not-using-storybook-youre-doing-fe-development-wrong-2bk1</guid>
      <description>&lt;p&gt;Before we get to it, this is a heavily &lt;strong&gt;opinionated&lt;/strong&gt; post so keep that in mind I like Storybook a lot so that should also be noted.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why&lt;/li&gt;
&lt;li&gt;How&lt;/li&gt;
&lt;li&gt;So you've heard "Storybook takes me longer to implement components." I'm here to say it does not.&lt;/li&gt;
&lt;li&gt;Let's talk about Autodocs because it's too awesome to leave out&lt;/li&gt;
&lt;li&gt;Why would I not use Storybook?&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;Let's start at the beginning: what is Storybook, and why should I use it?&lt;/p&gt;

&lt;p&gt;For those who have not had the chance to use Storybook before, it's incredibly easy to set up and takes little to no time. I won't go into the setup process here, as I'm covering that in a separate post along with some tips and tricks I normally use.&lt;/p&gt;

&lt;p&gt;Storybook has recently implemented zero-config support for most CSS solutions, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💨 Tailwind&lt;/li&gt;
&lt;li&gt;🧶 MaterialUI&lt;/li&gt;
&lt;li&gt;💅 Styled Components&lt;/li&gt;
&lt;li&gt;👩‍🎤 Emotion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But let's get back to what Storybook actually does and the problems it solves.&lt;/p&gt;

&lt;p&gt;This is just a condensed version of the Storybook documentation, which is available &lt;a href="https://storybook.js.org/docs/react/get-started/why-storybook" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Over recent times, complexity with UIs and frontend development has been growing. Starting with responsive design, a typical component now has multiple factors to consider. For example, if you have a button that has 3 variants (with different background colors), you then have to check that variant on each modern browser (4). Additionally, you need to test this component on countless breakpoints. Managing all of this while ensuring no regression issues arise and all components work seamlessly becomes quite a headache.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytw91w4h2i43fuw00pcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytw91w4h2i43fuw00pcl.png" alt="Storybook Component Complexity" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's where Storybook bridges the gap. It can help you keep these variations and states in check across all browsers and breakpoints with some help from tools like Chromatic (also made by the Storybook team).&lt;/p&gt;

&lt;h2&gt;
  
  
  How
&lt;/h2&gt;

&lt;p&gt;In short, before my new blog post comes out, run the following command in the repository where you want to install Storybook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx storybook@latest init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you're off to the races! It will ask some questions about your repository, so answer them correctly, and Storybook will be set up out of the box and ready to go.&lt;/p&gt;

&lt;p&gt;For small plugins like the a11y plugin, which injects AXE accessibility tests into your stories, it's rather simple to add as well.&lt;/p&gt;

&lt;h2 id="1"&gt; "Storybook takes me longer to implement components" – I'm here to say it does not.&lt;/h2&gt;

&lt;p&gt;I've heard this complaint a lot. If your components are built in isolation and have data passed to them, you're primed to just copy and paste the same story over and over again. At the very least, with this approach, you get some documentation automatically generated, as well as all the extra bells and whistles that Storybook provides (a11y, testing, etc.).&lt;/p&gt;

&lt;p&gt;This takes zero time. I mean, let's be real – the most you would do if you wanted a sleek-looking Storybook is to write your documentation alongside the code, for everyone to enjoy, instead of using Confluence or other external tools.&lt;/p&gt;

&lt;p&gt;If you need some templates to steal, take a look at my &lt;a href="https://github.com/Nevnet99/Ecommerce-strapi" rel="noopener noreferrer"&gt;ecommerce project&lt;/a&gt; that I'm building. I'm using Storybook extensively. At the time of writing, I haven't even touched Next.js. Instead, I'm building out each component before adding it to the main site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's talk about Autodocs because it's too awesome to leave out
&lt;/h2&gt;

&lt;p&gt;Autodocs are cool! &lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7076919268012871680?utm_source=share&amp;amp;utm_medium=member_desktop" rel="noopener noreferrer"&gt;Here's&lt;/a&gt; a link to a video explaining Autodocs. This feature allows you to write extensive documentation with almost zero effort – just copy and paste&lt;/p&gt;

&lt;p&gt;Tell me why I'm wrong in the comments below. I'm releasing a new blog post about how I work with Storybook soon, so look out for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would I not use Storybook?
&lt;/h2&gt;

&lt;p&gt;I'm not quite sure. Storybook has loads of benefits and can help create a robust, clean application. Not using it is pure insanity and inevitably leads to spaghetti code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Hopefully, I've helped you see the light, and you'll choose Storybook for your next project. You'll get free documentation, regression testing, a11y testing, and interaction testing built-in with just around 10 minutes of effort for the setup.&lt;/p&gt;

&lt;p&gt;🚀 Feel free to reach out if you have any questions or thoughts. Happy coding!&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>react</category>
      <category>storybook</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Accessibility - Getting started / Quick wins</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Sun, 25 Jun 2023 15:44:35 +0000</pubDate>
      <link>https://dev.to/nevnet99/accessibility-getting-started-quick-wins-54o4</link>
      <guid>https://dev.to/nevnet99/accessibility-getting-started-quick-wins-54o4</guid>
      <description>&lt;p&gt;Contents:&lt;/p&gt;

&lt;p&gt;The reason I'm writing this blog post is due to the current way that accessibility at least in my experience is seen within tech companies. An afterthought or an oops yeah we should've done that at the start.&lt;/p&gt;

&lt;p&gt;Accessibility is one of the topics, that for me is as important if not more important than testing (There is no point in testing something if it does not work for people who can only use a keyboard). But opinions aside there is a risk to bad accessibility and that is if whoever you're working for client or business asks we need to meet X standard there is either going to be a lot of refactoring or a complete remake of some components.&lt;/p&gt;

&lt;p&gt;A couple of components to look out for are (although this is not a complete list that can be found &lt;a href="https://www.w3.org/TR/WCAG21/" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tabbed views&lt;/li&gt;
&lt;li&gt;Accordions&lt;/li&gt;
&lt;li&gt;Fake buttons&lt;/li&gt;
&lt;li&gt;Buttons with no text (Icon buttons etc)&lt;/li&gt;
&lt;li&gt;Custom selects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you're looking to learn more semantic HTML learning accessibility in tandem is a really good idea as some semantic elements, for example, the interactive element &lt;code&gt;&amp;lt;dialog&amp;gt;&amp;lt;/dialog&amp;gt;&lt;/code&gt; (we'll get into this in a bit).&lt;/p&gt;

&lt;p&gt;In this post, I'm aiming to get you started or at least point you in the right direction when it comes to accessibility, giving you the confidence as well as knowledge to spot common errors before they become large issues causing you to refactor major components within a codebase. Let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aria Labels
&lt;/h2&gt;

&lt;p&gt;An &lt;code&gt;aria-label&lt;/code&gt; is an attribute for an HTML element that defines a label for the given element. It should be used when there is no visible text associated with an element. Aria labels should only be used on certain elements, don't go labeling everything!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interactive elements&lt;/li&gt;
&lt;li&gt;Landmark elements&lt;/li&gt;
&lt;li&gt;Elements that have an explicit widget role&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;iframe&lt;/code&gt; and &lt;code&gt;img&lt;/code&gt; elements (I don't think these need an explanation 🙂)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's expand on what some of these elements are.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive elements
&lt;/h3&gt;

&lt;p&gt;Interactive elements consist of 4 HTML elements (blog post explaining how to use these coming soon! for now here's a link to some &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element#interactive_elements" rel="noopener noreferrer"&gt;docs&lt;/a&gt;!).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;details&amp;gt;&amp;lt;/details&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;dialog&amp;gt;&amp;lt;/dialog&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;menu&amp;gt;&amp;lt;/menu&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;summary&amp;gt;&amp;lt;/summary&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Landmark elements
&lt;/h3&gt;

&lt;p&gt;Landmark elements are a special kind of element; it could technically be any HTML element with the role set to a valid landmark value. A list of these is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;banner&lt;/code&gt;: A region that contains the prime heading or internal title of a page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;complementary&lt;/code&gt;: Any section of the document that supports the main content, yet is separate and meaningful on its own.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;contentinfo&lt;/code&gt;: A region that contains information about the parent document such as copyrights and links to privacy statements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;form&lt;/code&gt;: A region of the document that represents a collection of form-associated elements, some of which can represent editable values that can be submitted to a server for processing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;main&lt;/code&gt;: Main content in a document. In almost all cases, a page will have only one &lt;code&gt;role="main"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;navigation&lt;/code&gt;: A collection of links suitable for use when navigating the document or related documents.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search&lt;/code&gt;: The search tool of a Web document.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;application&lt;/code&gt;: A region declared as a web application, as opposed to a web document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I apologize for the incomplete response. Here's the continuation of the blog post:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessibility - Getting started / Quick wins&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Elements with explicit widget role
&lt;/h3&gt;

&lt;p&gt;Some elements have an explicit role that represents a specific widget or interactive component. These elements include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For these elements, if they don't have visible text, you should provide an &lt;code&gt;aria-label&lt;/code&gt; to ensure they are accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of using &lt;code&gt;aria-label&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Let's take a look at a few examples of how to use &lt;code&gt;aria-label&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Button with an icon:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Add item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon-add"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the button has an icon but no visible text. The &lt;code&gt;aria-label&lt;/code&gt; attribute provides an accessible label for screen readers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Image with no alt text:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Product image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using an image without alt text, you can use the &lt;code&gt;aria-label&lt;/code&gt; attribute to provide a description for screen reader users.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Custom select dropdown:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"combobox"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Select a country"&lt;/span&gt; &lt;span class="na"&gt;aria-expanded=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;aria-autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"listbox"&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"option"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Option 1&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"option"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Option 2&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"option"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Option 3&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have a custom select dropdown implemented using HTML and CSS. The &lt;code&gt;aria-label&lt;/code&gt; attribute on the main container provides a label for the dropdown, and the &lt;code&gt;role&lt;/code&gt; attributes on the child elements define their roles for accessibility.&lt;/p&gt;

&lt;p&gt;By using &lt;code&gt;aria-label&lt;/code&gt; appropriately, you can ensure that elements without visible text are still accessible to screen reader users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyboard Accessibility
&lt;/h2&gt;

&lt;p&gt;Keyboard accessibility is a crucial aspect of web accessibility. Many users rely on keyboards to navigate and interact with websites, especially those with motor disabilities. Here are some key points to consider for keyboard accessibility:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Focus Styles&lt;/strong&gt;: Ensure that interactive elements, such as links, buttons, and form inputs, have a visible focus indicator when they receive focus. This helps keyboard users understand their current location on the page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tab Order&lt;/strong&gt;: Elements should follow a logical tab order that makes sense for keyboard users. By default, HTML elements are ordered based on their position in the HTML document. However, you can use the &lt;code&gt;tabindex&lt;/code&gt; attribute to modify the tab order if needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keyboard Navigation&lt;/strong&gt;: Test your website using only the keyboard to ensure all interactive elements are reachable and operable. Users should be able to navigate through links, buttons, dropdown menus, and other interactive components using the keyboard alone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Skip Links&lt;/strong&gt;: Include a skip link at the beginning of your page to allow users to jump directly to the main content or other important sections. This helps keyboard users avoid repetitive navigation and quickly access the relevant content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keyboard Traps&lt;/strong&gt;: Avoid creating keyboard traps where users get stuck in a particular focus state and cannot navigate away using the keyboard. For example, ensure that modals and overlays can be closed using the keyboard (e.g., pressing the Escape key).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are just a few considerations for keyboard accessibility. It's important to thoroughly test your website's keyboard interactions and ensure a smooth experience for keyboard-only users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Semantic HTML
&lt;/h2&gt;

&lt;p&gt;Using semantic HTML is not only good for search engine optimization and code readability but also plays a significant role in accessibility. Semantic HTML&lt;/p&gt;

&lt;p&gt;elements convey meaning to assistive technologies and provide context for understanding the structure of a web page. Here are some examples of semantic HTML elements and their usage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;: Represents the introductory content or a group of navigational aids for a page or section.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;: Defines a section containing navigation links.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;: Specifies the main content of a document.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;: Represents a self-contained composition in a document.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;: Defines a standalone section within a document.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt;: Represents a section of a document with content related to the main content.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;: Defines the footer of a document or a section.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;figcaption&amp;gt;&lt;/code&gt;: Used together to encapsulate media content (such as images) and provide a caption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By utilizing these semantic elements, you provide additional context to assistive technologies and enhance the overall accessibility of your website.&lt;/p&gt;

&lt;h2&gt;
  
  
  ARIA Landmarks
&lt;/h2&gt;

&lt;p&gt;ARIA landmarks are a set of roles that can be added to specific sections of a web page to help users navigate and understand its structure. Some common ARIA landmarks include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;role="banner"&lt;/code&gt;: Marks the banner or header section of a page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;role="navigation"&lt;/code&gt;: Identifies the section containing navigation links.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;role="main"&lt;/code&gt;: Marks the main content of a document.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;role="complementary"&lt;/code&gt;: Identifies a section that supports the main content but is not essential to its understanding.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;role="contentinfo"&lt;/code&gt;: Marks the footer or the end portion of a page, providing additional information about the document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using ARIA landmarks, you can enhance the navigation and comprehension of your web pages for screen reader users.&lt;/p&gt;

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

&lt;p&gt;Web accessibility is a vital aspect of building inclusive and user-friendly websites. By following these quick wins, including providing explicit widget roles, using &lt;code&gt;aria-label&lt;/code&gt; appropriately, ensuring keyboard accessibility, using semantic HTML, and leveraging ARIA landmarks, you can make significant improvements to the accessibility of your website.&lt;/p&gt;

&lt;p&gt;Remember that accessibility is an ongoing process, and it's essential to test your website with real users, including those with disabilities, to gather feedback and make further improvements. By prioritizing accessibility from the start and continuously iterating on your designs and implementations, you can create a web experience that is accessible to all users.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>useCallback and useMemo: Understanding Performance Hooks.</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Sun, 25 Jun 2023 15:36:45 +0000</pubDate>
      <link>https://dev.to/nevnet99/usecallback-and-usememo-understanding-performance-hooks-3eoh</link>
      <guid>https://dev.to/nevnet99/usecallback-and-usememo-understanding-performance-hooks-3eoh</guid>
      <description>&lt;h2&gt;
  
  
  Memoization
&lt;/h2&gt;

&lt;p&gt;Before we dive into the hooks, it will be beneficial to understand what memoization is. In computing, memoization or memoisation is an optimization technique used primarily to speed up computer programs. It involves storing the results of expensive function calls and returning the cached result when the same inputs occur again.&lt;/p&gt;

&lt;p&gt;To put it simply, when we refer to a function as "expensive," it means that the function takes a long time to complete. This could be due to various reasons such as complex computations or waiting for a response from an API.&lt;/p&gt;

&lt;p&gt;If you'd like to explore memoization further, I recommend reading &lt;a href="https://betterprogramming.pub/javascript-memoization-and-expensive-code-1a0aaa37a241" rel="noopener noreferrer"&gt;this&lt;/a&gt; blog post for more information.&lt;/p&gt;

&lt;h2&gt;
  
  
  useMemo
&lt;/h2&gt;

&lt;p&gt;Now that we understand memoization, you might have an idea of what useMemo can be used for. useMemo, short for memoization, is used for storing the results of expensive function calls and returning the cached result when the same inputs occur again (sound familiar? 👀).&lt;/p&gt;

&lt;p&gt;Let's break it down with an example. Consider the following expensive function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getPhrase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phraseType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Added to simulate an expensive function&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phraseType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greeting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;goodbye&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, I've added a while loop to simulate an expensive function. It could be replaced with any other computationally intensive task, such as making a call to an API that returns a large amount of data.&lt;/p&gt;

&lt;p&gt;Now, let's apply this to a React component.&lt;/p&gt;

&lt;p&gt;You can find the code &lt;a href="https://stackblitz.com/edit/react-yzrica?file=src/Phrase.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;When you choose "Preview" in the top-right corner, you can see the component in action.&lt;/p&gt;

&lt;p&gt;Try clicking the "Increment" button rapidly. Notice that it's slow to update the counter value. This slowness is caused by the expensive function being called on every re-render of the component. We can address this performance issue using useMemo.&lt;/p&gt;

&lt;p&gt;Check out the updated code &lt;a href="https://stackblitz.com/edit/react-wvrwwffile=src/Phrase.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Now, if you use the "Increment" button, it responds instantly. &lt;/p&gt;

&lt;p&gt;Let's analyze what we have learned from memoization and apply it to the useMemo hook.&lt;/p&gt;

&lt;p&gt;Here's the key change between the slow and fast examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getPhrase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we know from memoization, it's an optimization technique that stores the results of expensive function calls and returns the cached result when the same inputs occur again.&lt;/p&gt;

&lt;p&gt;useMemo accepts two arguments. The first argument is a function that you want to apply memoization to, and the second argument is a dependency array. The function itself is self-explanatory: in our case, we want to apply useMemo to &lt;code&gt;getPhrase&lt;/code&gt; since it's an expensive function. &lt;/p&gt;

&lt;p&gt;The dependency array might sound more complex than it actually is. If the values provided in the dependency array change, our expensive function will be executed again. However, if they don't change, React will use the cached result instead of re-running the function to obtain a new result (which explains the performance increase in the above example).&lt;/p&gt;

&lt;p&gt;Consider the following example where we have added the &lt;code&gt;counter&lt;/code&gt; to the dependency array. Now, as expected, our component becomes slow again because the &lt;code&gt;counter&lt;/code&gt; variable changes, causing the component to re-render.&lt;/p&gt;

&lt;p&gt;Check out the example &lt;a href="https://stackblitz.com/edit/react-9wumfvfile=src/Phrase.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's all for &lt;code&gt;useMemo&lt;/code&gt;. By now, you should have a strong understanding of memoization and knowledge of how and where to use the &lt;code&gt;useMemo&lt;/code&gt; hook to achieve performance gains.&lt;/p&gt;

&lt;h2&gt;
  
  
  useCallback
&lt;/h2&gt;

&lt;p&gt;Now that you understand &lt;code&gt;useMemo&lt;/code&gt;, let's move on to &lt;code&gt;useCallback&lt;/code&gt;. &lt;code&gt;useCallback&lt;/code&gt; is similar to &lt;code&gt;useMemo&lt;/code&gt;, as it also accepts two arguments: a function and a dependency array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;someFunction&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;someDependency&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, instead of caching the return value of the function, &lt;code&gt;useCallback&lt;/code&gt; caches the function instance itself, preserving the same instance until one of the dependencies changes.&lt;/p&gt;

&lt;p&gt;Let's break it down with an example. Below is a React component with two click handlers and a counter that tracks the number of new functions created in the component.&lt;/p&gt;

&lt;p&gt;Check out the code &lt;a href="https://stackblitz.com/edit/react-hps3gr?file=src%2FSomeComponent.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each click of the "Increment" button creates two new functions per render. This example demonstrates the behavior without &lt;code&gt;useCallback&lt;/code&gt;. Keep in mind that this is just to showcase what &lt;code&gt;useCallback&lt;/code&gt; does; it may not necessarily be the best approach in this specific case.&lt;/p&gt;

&lt;p&gt;Now, check out the updated code &lt;a href="https://stackblitz.com/edit/react-56vhrg?file=src%2FSomeComponent.js" rel="noopener noreferrer"&gt;here&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;after applying &lt;code&gt;useCallback&lt;/code&gt;. Click the buttons, and you'll notice that no extra functions are created per render.&lt;/p&gt;

&lt;p&gt;In my opinion, the primary use case for &lt;code&gt;useCallback&lt;/code&gt; is when you're using a function as a dependency for another hook. Although there are other use cases, I find them to be rare. Take the following code as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyApp&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;memoizedFoo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do something with state or props data&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/* related state/props */&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do something with memoizedFoo&lt;/span&gt;
    &lt;span class="c1"&gt;// maybe fetch data from an API and pass it to memoizedFoo&lt;/span&gt;
    &lt;span class="nf"&gt;memoizedFoo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;memoizedFoo&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;...&lt;span class="p"&gt;&amp;lt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find an example &lt;a href="https://stackoverflow.com/questions/66429202/what-are-production-use-cases-for-the-useref-usememo-usecallback-hooks" rel="noopener noreferrer"&gt;here&lt;/a&gt; (thanks 🥰).&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;useCallback&lt;/code&gt;, this &lt;code&gt;useEffect&lt;/code&gt; would execute on every re-render and ignore the dependency of &lt;code&gt;memoizedFoo&lt;/code&gt;. As shown in the previous examples, functions are recreated on each re-render, which is NOT desirable. However, &lt;code&gt;useCallback&lt;/code&gt; prevents this by using the memorized instance of the &lt;code&gt;memoizedFoo&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;It's worth mentioning that it's not always the best approach to use &lt;code&gt;useCallback&lt;/code&gt; for all your functions, although it might be tempting to do so. Kent C Dodds wrote an excellent blog post about when to use and when not to use &lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt;. You can check it out &lt;a href="https://kentcdodds.com/blog/usememo-and-usecallback" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Microrepos vs. Monorepo: Understanding the Differences 🥷🏻</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Sun, 25 Jun 2023 15:29:35 +0000</pubDate>
      <link>https://dev.to/nevnet99/microrepos-vs-monorepo-understanding-the-differences-292m</link>
      <guid>https://dev.to/nevnet99/microrepos-vs-monorepo-understanding-the-differences-292m</guid>
      <description>&lt;p&gt;Welcome to this blog post where we'll explore the differences between Microrepos and Monorepo. As I delve into the topic, I'll solidify my knowledge and share valuable insights with you. So, let's embark on this journey together!&lt;/p&gt;

&lt;h2&gt;
  
  
  Microrepos
&lt;/h2&gt;

&lt;p&gt;Let's begin by understanding what a Microrepo is. Essentially, a Microrepo refers to a specific service of an application that has been separated from other services. These services work together to create a unified application, rather than existing as standalone repositories.&lt;/p&gt;

&lt;p&gt;While examining Microrepos, we uncover some intriguing benefits:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Clear separation: Each microservice resides in its own repository, ensuring distinct boundaries between services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Independent deployment: Microservices can be deployed individually, enabling faster release cycles and reducing dependencies between services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Autonomy: Each team responsible for a microservice has full control over its development, testing, and deployment processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flexibility: Different services can use diverse technologies or programming languages based on their specific requirements.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, alongside these benefits, some challenges also arise:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Increased complexity: Managing multiple repositories for each microservice introduces additional complexity in terms of repository organization, version control, and dependency management. It requires careful coordination and may demand a more sophisticated tooling setup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Communication and coordination overhead: With Microrepos, different development teams may work on separate repositories, potentially leading to communication and coordination challenges. Synchronizing changes and ensuring compatibility between microservices can become intricate, necessitating effective collaboration and communication channels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment and testing overhead: Deploying and testing multiple microservices individually can be more time-consuming and resource-intensive compared to a monolithic deployment. Ensuring the compatibility and integration of all services during the deployment process may require additional effort and thorough testing procedures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependency duplication: Each microservice typically has its own set of dependencies. With Microrepos, there is a possibility of duplicated dependencies across different repositories. This can result in increased storage requirements and potential difficulties in managing and updating dependencies consistently.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monorepo
&lt;/h2&gt;

&lt;p&gt;Now, let's shift our focus to Monorepo, which stands in stark contrast to Microrepos. In a Monorepo, the entire code base is stored within a single repository, along with all related dependencies.&lt;/p&gt;

&lt;p&gt;Let's explore the advantages of a Monorepo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Centralized codebase: All the code for an application is stored in a single repository, making it easier to manage and maintain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shared dependencies: Components and libraries can be shared among different parts of the application, promoting code reuse.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consistent development environment: Developers have a unified view of the entire codebase, facilitating collaboration and enabling consistent testing and debugging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simplified refactoring: When making changes that span multiple services, refactoring and maintaining consistency becomes easier within a Monorepo.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, Monorepos also present some challenges:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Increased repository size: With a Monorepo, the entire codebase is stored in a single repository, which can lead to a significant increase in its size over time. Large repositories can impact the performance of version control systems and make cloning or updating the repository time-consuming.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Coupling of components: In a Monorepo, all components of an application are tightly coupled within the same repository. Changes made to one component can potentially impact other components, making it essential to exercise caution and thorough testing when modifying shared code or dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build and test times: As the codebase grows, the build and test times for the entire Monorepo can increase. Even small changes may trigger full rebuilds and retesting processes for the entire application, leading to longer development cycles and slower feedback loops.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limited technology flexibility: In a Monorepo, all components of the application&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;share the same technology stack and dependencies. This can limit the flexibility of choosing different technologies or programming languages for specific components or services, which may be necessary for certain use cases or teams with different expertise.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Collaboration challenges: With a Monorepo, all developers work within the same repository, potentially leading to conflicts and challenges when multiple developers make changes simultaneously. Resolving merge conflicts can be time-consuming and requires effective coordination and communication among team members.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security risks: In a Monorepo, access controls and permissions need to be carefully managed to ensure that only authorized individuals have access to sensitive parts of the codebase. Misconfigurations or lapses in access control can pose security risks and potentially expose the entire codebase to unauthorized access.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Clearly, both Microrepos and Monorepo have their pros and cons, and choosing the right approach depends on the specific context of the application you're building.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Opinionated Perspective&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a front-end developer, I personally lean towards favoring the use of Microrepos more often. The flexibility and independent releases offered by Microrepos are powerful advantages compared to the typical Monorepo structure. However, it's important to address concerns related to excessive service splitting, which can be avoided through careful consideration and strong collaboration within the team. Each decision to split services should account for the additional overhead it introduces to the entire application, including testing, releases, and other factors.&lt;/p&gt;

&lt;p&gt;❗️ A really good read about over sharding can be found &lt;a href="https://www.primevideotech.com/video-streaming/scaling-up-the-prime-video-audio-video-monitoring-service-and-reducing-costs-by-90" rel="noopener noreferrer"&gt;here&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;with the recent split from amazon prime video going from microservices -&amp;gt; monorepo &lt;/p&gt;

&lt;p&gt;Now that we have explored the nuances of Microrepos and Monorepo, you can make an informed decision based on your project requirements and trade-offs.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>WTF is HAL (Hypertext Application Language)</title>
      <dc:creator>Luke Brannagan</dc:creator>
      <pubDate>Sun, 25 Jun 2023 14:02:31 +0000</pubDate>
      <link>https://dev.to/nevnet99/wtf-is-hal-hypertext-application-language-2fo6</link>
      <guid>https://dev.to/nevnet99/wtf-is-hal-hypertext-application-language-2fo6</guid>
      <description>&lt;p&gt;So you've found yourself making decisions about an API, and are interested in Hypertext Application Language. &lt;/p&gt;

&lt;p&gt;So I'm writing this specific blog post to learn as we go along, so come along for the journey. I hope you enjoy it! &lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Background&lt;/li&gt;
&lt;li&gt;How do I use HAL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Hypertext Application Language (HAL) is a convention for defining hypermedia links within JSON or XML code. It simplifies API development by making APIs more discoverable and allowing easy interaction using JSON or XML. HAL uses a special media type (application/hal+json or application/xml+json) to indicate its usage. It facilitates linking resources, such as books and authors, by including _links objects. These links can be used to navigate between resources and perform actions. HAL offers a minimal impact approach and enables the creation of general-purpose libraries for APIs.&lt;/p&gt;

&lt;p&gt;You can customize the table of contents based on the headings and sections in your document. Simply replace the example headings and section links with your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Background
&lt;/h2&gt;

&lt;p&gt;Let's start off with Wikipedia's definition of what Hypertext Application Language is: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hypertext Application Language (HAL) is a convention for defining hypermedia such as links to external resources within JSON or XML code. It is documented in an Internet Draft (a "work in progress"), however, the latest version of HAL Internet-Draft expired on November 12, 2016. The standard was initially proposed in June 2012 specifically for use with JSON[1] and has since become available in two variations, JSON and XML. The two associated MIME types are media type: application/hal+xml and media type: application/hal+json.&lt;/p&gt;

&lt;p&gt;HAL was created to be simple to use and easily applicable across different domains by avoiding the need to impose any requirements on how the project be structured. Maintaining this minimal impact approach, HAL has enabled developers to create general-purpose libraries which can be easily incorporated on any API that uses HAL.&lt;/p&gt;

&lt;p&gt;APIs that adopt HAL simplify the use of open source libraries and make it possible to interact with the API using JSON or XML. The alternative would be having to develop a proprietary format which in turn forces developers to learn how to use yet another foreign format.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Hypertext_Application_Language" rel="noopener noreferrer"&gt;source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From this point on, Hypertext Application Language will be referred to as HAL.&lt;/p&gt;

&lt;p&gt;So, to unpack that and to make it easier to read, here is my interpretation of this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HAL is used to handle links across your API and make your API more discoverable.&lt;/li&gt;
&lt;li&gt;HAL can be used for both internal routes as well as routes external to your application, despite being only mentioned here as external.&lt;/li&gt;
&lt;li&gt;HAL has a special media type &lt;code&gt;application/hal+json&lt;/code&gt; or &lt;code&gt;application/xml+json&lt;/code&gt;. This should be used to let clients of your API know that you are using HAL.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How do I use HAL?
&lt;/h2&gt;

&lt;p&gt;Let's start with an example of a bookstore.&lt;/p&gt;

&lt;p&gt;Endpoint: GET /books/{bookId}&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Hobbit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"genre"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fantasy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"J.R.R. Tolkien"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/authors/1"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/books/1"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you send a GET request to retrieve information about a specific book with the ID 1, the API responds with the book's details, including its title, genre, and the author associated with it. The response follows the HAL format. The book resource includes a link to the author's resource using the &lt;code&gt;_links&lt;/code&gt; object, where the &lt;code&gt;self&lt;/code&gt; link points to the URL for the author resource.&lt;/p&gt;

&lt;p&gt;Endpoint: GET /authors/{authorId}&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"J.R.R. Tolkien"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"books"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Hobbit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/books/1"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Lord of the Rings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/books/2"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/authors/1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you send a GET request to retrieve information about a specific author with the ID 1, the API responds with the author's details, including their name and the books they have written. The response follows the HAL format. The author resource includes a list of books, each represented as a separate object with its own &lt;code&gt;_links&lt;/code&gt; object. These links point to the URLs for the respective book resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;_links&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;_links&lt;/code&gt; key can include a wide array of keys. In the book example, we could add a "next" key to show the next book in the series or even a "prev" to show the previous book in the series.&lt;/p&gt;

&lt;p&gt;It's also a great place to link together actions. For example, editing a book would now include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Hobbit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/books/1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/books/2"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"edit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/books/2/edit"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
